Selfbalancing
Selfbalancing
1. Introduction
2. Block Diagram
lua
CopyEdit
+-------------------------+
| |
| Inertial Sensors |
| (Gyroscope, Accelerometer) |
+-----------+-------------+
+-------+--------+
| |
| Arduino |
| (Controller) |
+-------+--------+
+----------+-----------+
| |
| |
+----------+-----------+
v
+---------+---------+
| |
| |
+-------------------+
Explanation:
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
1 Arduino UNO 1
4 BO-type DC Motors 2
5 Robot Chassis 1
6 Wheels 2
7 Castor Wheel 1
S.No Component Quantity
As
9 Jumper Wires
needed
10 Power Supply 1
5. Hardware Connections
o VCC → 5V (Arduino)
o SDA → A4 (Arduino)
o SCL → A5 (Arduino)
o ENA → 5V (Arduino)
o ENB → 5V (Arduino)
DC Motors:
Power Supply:
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.
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.
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.
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;
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];
void dmpDataReady() {
mpuInterrupt = true;
void setup() {
Serial.begin(115200);
mpu.initialize();
if (mpu.testConnection()) {
} else {
return;
}
devStatus = mpu.dmpInitialize();
if (devStatus == 0) {
mpu.setDMPEnabled(true);
mpuIntStatus = mpu.getIntStatus();
packetSize = mpu.dmpGetFIFOPacketSize();
pid.SetMode(AUTOMATIC);
pid.SetSampleTime(10);
pid.SetOutputLimits(-255, 255);
} else {
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;
pid.Compute();
} else {
Stop();
mpuInterrupt = false;
mpuIntStatus = mpu.getIntStatus();
fifoCount = mpu.getFIFOCount();
mpu.resetFIFO();
Serial.println(F("FIFO overflow!"));
mpu.getFIFOBytes(fifoBuffer, packetSize);
fifoCount -= packetSize;
mpu.dmpGetQuaternion(&q, fifoBuffer);
mpu.dmpGetGravity(&gravity, &q);
void Forward() {
analogWrite(6, output);
analogWrite(9, 0);
analogWrite(10, output);
analogWrite(11, 0);
Serial.print("F");
void Reverse() {
analogWrite(6, 0);
analogWrite(10, 0);
Serial.print("R");
void Stop() {
analogWrite(6, 0);
analogWrite(9, 0);
analogWrite(10, 0);
analogWrite(11, 0);
Serial.print("S");
┌─────────────────────────┐
│ START │
└────────────┬────────────┘
│
▼
┌────────────────────────────────────────────┐
│ offsets. │
└───────────────┬────────────────────────────┘
devStatus ≠ 0 │
┌───────────────▼────────────────────────────┐
└────────────────────────────────────────────┘
devStatus = 0 │
▼
┌────────────────────────────────────────────┐
│ get packetSize │
└────────────────────────────────────────────┘
▼
┌────────────────────────────────────────────┐
│ Initialize PID: │
│ SetMode(AUTOMATIC), SampleTime(10ms), │
│ OutputLimits(-255, +255) │
└────────────────────────────────────────────┘
▼
┌────────────────────────────────────────────┐
▼
┌────────────────┐
│ MAIN LOOP │
└───┬─────────────┘
┌─────────────▼─────────────┐
│ fifoCount ≥ packetSize │
└─────────────┬─────────────┘
▼
┌────────────────────────────────────────────┐
│ Decrement fifoCount │
└────────────────────────────────────────────┘
▼
┌────────────────────────────────────────────┐
│ mpu.dmpGetQuaternion() │
│ mpu.dmpGetGravity() │
│ mpu.dmpGetYawPitchRoll(ypr) │
└────────────────────────────────────────────┘
▼
┌────────────────────────────────────────────┐
└────────────────────────────────────────────┘
▼
┌────────────────────────────────────────────┐
│ PID compute: │
│ pid.Compute() → output │
└────────────────────────────────────────────┘
▼
┌────────────────────────────────────────────┐
└───────┬───────────────────┬────────────────┘
│ Yes │ No
│ │
▼ ▼
┌───────────────────┐ ┌───────────────────┐
│ │ │ Stop() │
└──────┬────────────┘ └───────────────────┘
│ (drive both │
│ wheels forward) │
└──────────────────┘
│ No (i.e. output<0)
▼
┌──────────────────┐
│ Reverse() │
│ (drive both │
│ wheels backward)│
└──────────────────┘
▼
┌───────────┐
│ Loop back │
└───────────┘