Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Miguel_Corza
Published © CC0

Balancing Robot

Robot made with arduino that self-balances using PID control. You can see its construction, behavior with graphs, video, and codes here! 🤖

IntermediateFull instructions provided6 hours478
Balancing Robot

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
SparkFun Motor Driver - Dual TB6612FNG (1A)
SparkFun Motor Driver - Dual TB6612FNG (1A)
×1
Ethernet Cable, Cat6a
Ethernet Cable, Cat6a
×1
pcb board
×1
Inertial Measurement Unit (IMU) (6 deg of freedom)
Inertial Measurement Unit (IMU) (6 deg of freedom)
×1

Software apps and online services

MATLAB
MATLAB

Story

Read more

Schematics

Balancing robot schematic.

Code

PID robot Arduino code

Arduino
kp, ki, and kd are constants that vary with the different sizes and weights of the robot.
#include <PID_v1.h>
#include <LMotorController.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include <SoftwareSerial.h>
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
#define MIN_ABS_SPEED 30
MPU6050 mpu;
double MotorVelocidadIzq = 0.5;
double MotorVelocidadDer = 0.5;
double PuntoEquilibrio = 185.3;
SoftwareSerial Serial_2 (4, 3);
int ENA = 5;
int IN1 = 6;
int IN2 = 7;
int IN3 = 9;
int IN4 = 8;
int ENB = 10;
double Kp =0 .7;
double Kd = 17;
double Ki = 100;
int estado = 'g';
bool dmpReady = false;
uint8_t mpuIntStatus;
uint8_t devStatus;
uint16_t packetSize;
uint16_t fifoCount;
uint8_t fifoBuffer[64];
Quaternion q;
VectorFloat gravity;
float ypr[3];
double originalSetpoint = PuntoEquilibrio;
double setpoint = originalSetpoint;
double movingAngleOffset = 0.1;
double input, output;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);
double motorSpeedFactorLeft = MotorVelocidadIzq;
double motorSpeedFactorRight = MotorVelocidadDer;
LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, motorSpeedFactorLeft, motorSpeedFactorRight);
volatile bool mpuInterrupt = false;
void dmpDataReady()
{
mpuInterrupt = true;
}
void setup()
{
Serial_2.begin(9600);
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24;
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
mpu.initialize();
devStatus = mpu.dmpInitialize();
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
mpu.setZAccelOffset(1788);
if (devStatus == 0)
{
mpu.setDMPEnabled(true);
// enable Arduino interrupt detection
attachInterrupt(0, dmpDataReady, RISING);
mpuIntStatus = mpu.getIntStatus();

dmpReady = true;

packetSize = mpu.dmpGetFIFOPacketSize();
//setup PID
pid.SetMode(AUTOMATIC);
pid.SetSampleTime(10);
pid.SetOutputLimits(-255, 255);
}
else
Serial.print(F("DMP Initialization failed (code "));
Serial.print(devStatus);
Serial.println(F(")"));
}
}
void loop()
{
if (!dmpReady) return;
while (!mpuInterrupt && fifoCount < packetSize)
{
pid.Compute();
motorController.move(output, MIN_ABS_SPEED);
}

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

Credits

Miguel_Corza
2 projects • 3 followers
I am currently a student of electronics and a future engineer. I enjoy creating and inventing new electronic projects.
Contact
Thanks to Profe garcia.

Comments

Please log in or sign up to comment.