0% found this document useful (0 votes)
4 views14 pages

Selfbalancing

The self-balancing robot project involves creating an autonomous robot that maintains its balance using an Inertial Measurement Unit (IMU) and an Arduino controller. The robot adjusts its movements based on sensor data to stay upright, utilizing a PID control algorithm for stabilization. Key components include the MPU6050 IMU, Arduino UNO, L298N motor driver, and DC motors, with detailed hardware connections and code provided for implementation.

Uploaded by

adeivasundaram
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views14 pages

Selfbalancing

The self-balancing robot project involves creating an autonomous robot that maintains its balance using an Inertial Measurement Unit (IMU) and an Arduino controller. The robot adjusts its movements based on sensor data to stay upright, utilizing a PID control algorithm for stabilization. Key components include the MPU6050 IMU, Arduino UNO, L298N motor driver, and DC motors, with detailed hardware connections and code provided for implementation.

Uploaded by

adeivasundaram
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 14

Self-Balancing Robot Project

1. Introduction

A self-balancing robot is an autonomous system that maintains its balance


without external assistance. Using sensors such as an Inertial
Measurement Unit (IMU) consisting of a gyroscope and accelerometer, the
robot detects its orientation and adjusts its movements to stay upright.
The robot is commonly used in robotics competitions, educational
applications, and research for the development of autonomous systems.

2. Block Diagram

lua

CopyEdit

+-------------------------+

| |

| Inertial Sensors |

| (Gyroscope, Accelerometer) |

+-----------+-------------+

+-------+--------+

| |

| Arduino |

| (Controller) |

+-------+--------+

+----------+-----------+

| |

| Motor Driver (H-Bridge)|

| |

+----------+-----------+

v
+---------+---------+

| |

| DC Motors (L & R)|

| |

+-------------------+

Explanation:

 Inertial Sensors (Gyroscope & Accelerometer): These sensors detect


the robot's orientation and movements.

 Arduino: Acts as the controller, processing sensor data and


controlling motor actions.

 Motor Driver (H-Bridge): Powers the motors based on commands


from the Arduino.

 DC Motors: These drive the wheels, adjusting speed and direction to


maintain balance.

3. Working Principle

The robot works by continuously reading data from the accelerometer and
gyroscope to determine its tilt angle. The Arduino processes this data and
adjusts the speed and direction of the motors to keep the robot balanced.
If the robot tilts forward, the motors spin in reverse to bring it back
upright, and similarly, if it tilts backward, the motors spin forward to
correct the tilt.

4. Component List

S.No Component Quantity

1 Arduino UNO 1

MPU6050 IMU (Accelerometer +


2 1
Gyroscope)

3 Motor Driver (L298N H-Bridge) 1

4 BO-type DC Motors 2

5 Robot Chassis 1

6 Wheels 2

7 Castor Wheel 1
S.No Component Quantity

8 Battery Pack (7.4V or 12V) 1

As
9 Jumper Wires
needed

10 Power Supply 1

5. Hardware Connections

 IMU (MPU6050) Connections:

o VCC → 5V (Arduino)

o GND → GND (Arduino)

o SDA → A4 (Arduino)

o SCL → A5 (Arduino)

 Motor Driver (L298N) Connections:

o IN1 → Pin 9 (Arduino)

o IN2 → Pin 10 (Arduino)

o IN3 → Pin 11 (Arduino)

o IN4 → Pin 12 (Arduino)

o ENA → 5V (Arduino)

o ENB → 5V (Arduino)

o Motor A → Left Motor

o Motor B → Right Motor

 DC Motors:

o Left Motor → Connected to Motor A on L298N

o Right Motor → Connected to Motor B on L298N

 Power Supply:

o 7.4V or 12V battery for motor driver (L298N)

o Arduino powered via USB or external supply

6. Detailed Hardware Description


 MPU6050 (IMU): This sensor combines an accelerometer and
gyroscope to measure linear acceleration and angular velocity,
providing crucial tilt and rotation data.

 Arduino UNO: The central controller that reads data from the
MPU6050 and drives the motors to adjust the robot's position based
on the sensor input.

 L298N Motor Driver: Controls the speed and direction of the DC


motors based on the signals from the Arduino.

 DC Motors: Responsible for moving the robot's wheels, adjusting


their speed and direction to maintain balance.

7. Arduino Hardware Diagram


8. Code Explanation

The code for the self-balancing robot uses feedback control to adjust the
robot's tilt angle continuously. The MPU6050 (gyroscope and
accelerometer) provides the necessary data, and the Arduino processes
this to control the motors and maintain balance.

Key Components:
 PID Control: The robot uses a Proportional-Integral-Derivative (PID)
control algorithm to minimize the error between the current and
desired positions (upright). The PID constants (Kp, Ki, Kd) need to be
experimentally tuned.

o Kp (Proportional): Adjusts the robot's response based on the


current tilt error.

o Kd (Derivative): Helps smooth the oscillation by considering


the rate of change of tilt.

o Ki (Integral): Corrects for any accumulated error over time to


stabilize the robot quickly.

Tuning Process:

 Kp: Start with a small value and gradually increase. A value too low
may cause instability, while a value too high will cause excessive
oscillation.

 Kd: Tune to reduce oscillations. A proper Kd value reduces shaking


and helps stabilize the robot.

 Ki: Corrects accumulated errors. Too high a value may cause


overshooting, while too low will slow down the stabilization.

The surface should be rough enough to ensure proper friction between the
robot wheels and the ground.

9. Complete Code

#include "I2Cdev.h"

#include <PID_v1.h>

#include "MPU6050_6Axis_MotionApps20.h"

MPU6050 mpu;

// MPU control/status vars

bool dmpReady = false;

uint8_t mpuIntStatus;

uint8_t devStatus;

uint16_t packetSize;

uint16_t fifoCount;
uint8_t fifoBuffer[64];

// orientation/motion vars

Quaternion q;

VectorFloat gravity;

float ypr[3];

/********* Tune these 4 values for your BOT *********/

double setpoint= 182; // Perpendicular value from serial monitor

double Kp = 15; // Set this first

double Kd = 0.9; // Set this second

double Ki = 140; // Finally set this

/****** End of values setting *********/

double input, output;

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

volatile bool mpuInterrupt = false;

void dmpDataReady() {

mpuInterrupt = true;

void setup() {

Serial.begin(115200);

mpu.initialize();

if (mpu.testConnection()) {

Serial.println(F("MPU6050 connection successful"));

} else {

Serial.println(F("MPU6050 connection failed"));

return;
}

devStatus = mpu.dmpInitialize();

if (devStatus == 0) {

mpu.setDMPEnabled(true);

attachInterrupt(0, dmpDataReady, RISING);

mpuIntStatus = mpu.getIntStatus();

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

pinMode(6, OUTPUT);

pinMode(9, OUTPUT);

pinMode(10, OUTPUT);

pinMode(11, OUTPUT);

analogWrite(6, LOW);

analogWrite(9, LOW);

analogWrite(10, LOW);

analogWrite(11, LOW);

void loop() {
if (!dmpReady) return;

while (!mpuInterrupt && fifoCount < packetSize) {

pid.Compute();

Serial.print(input); Serial.print(" =>"); Serial.println(output);

if (input > 150 && input < 200) {

if (output > 0) Forward();

else if (output < 0) Reverse();

} else {

Stop();

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[1] * 180 / M_PI + 180;


}

void Forward() {

analogWrite(6, output);

analogWrite(9, 0);

analogWrite(10, output);

analogWrite(11, 0);

Serial.print("F");

void Reverse() {

analogWrite(6, 0);

analogWrite(9, output * -1);

analogWrite(10, 0);

analogWrite(11, output * -1);

Serial.print("R");

void Stop() {

analogWrite(6, 0);

analogWrite(9, 0);

analogWrite(10, 0);

analogWrite(11, 0);

Serial.print("S");

┌─────────────────────────┐

│ START │

└────────────┬────────────┘


┌────────────────────────────────────────────┐

│ Initialize MPU6050 DMP & set gyro/accel │

│ offsets. │

└───────────────┬────────────────────────────┘

devStatus ≠ 0 │

┌───────────────▼────────────────────────────┐

│ DMP init failed: print error & HALT │

└────────────────────────────────────────────┘

devStatus = 0 │


┌────────────────────────────────────────────┐

│ Enable DMP, attach interrupt, │

│ get packetSize │

└────────────────────────────────────────────┘


┌────────────────────────────────────────────┐

│ Initialize PID: │

│ SetMode(AUTOMATIC), SampleTime(10ms), │

│ OutputLimits(-255, +255) │

└────────────────────────────────────────────┘


┌────────────────────────────────────────────┐

│ Initialize motor pins (6,9,10,11) & STOP │


└────────────────────────────────────────────┘


┌────────────────┐

│ MAIN LOOP │

└───┬─────────────┘

┌─────────────▼─────────────┐

│ Wait for MPU interrupt OR │

│ fifoCount ≥ packetSize │

└─────────────┬─────────────┘


┌────────────────────────────────────────────┐

│ Read FIFO buffer into fifoBuffer[] │

│ Decrement fifoCount │

└────────────────────────────────────────────┘


┌────────────────────────────────────────────┐

│ Extract Quaternion, Gravity, YPR values │

│ mpu.dmpGetQuaternion() │

│ mpu.dmpGetGravity() │

│ mpu.dmpGetYawPitchRoll(ypr) │

└────────────────────────────────────────────┘


┌────────────────────────────────────────────┐

│ Compute current pitch-based input angle: │


│ input = ypr[1] * 180/π + 180 │

└────────────────────────────────────────────┘


┌────────────────────────────────────────────┐

│ PID compute: │

│ pid.Compute() → output │

└────────────────────────────────────────────┘


┌────────────────────────────────────────────┐

│ Decision: is input within dead-band? │

│ (150 < input < 200) │

└───────┬───────────────────┬────────────────┘

│ Yes │ No

│ │

▼ ▼
┌───────────────────┐ ┌───────────────────┐

│ Check output sign │ │ Stop both motors │

│ │ │ Stop() │

└──────┬────────────┘ └───────────────────┘

output > 0? ──► Yes ─────► ┌──────────────────┐

(lean forward) │ Forward() │

│ (drive both │

│ wheels forward) │

└──────────────────┘

│ No (i.e. output<0)


┌──────────────────┐

│ Reverse() │

│ (drive both │

│ wheels backward)│

└──────────────────┘


┌───────────┐

│ Loop back │

└───────────┘

You might also like