Self Balancing Robot
PENDAHULUAN
Perkembangan
teknologi robotika telah membuat kualitas kehidupan manusia semakin tinggi.
Saat ini perkembangan teknologi robotika telah mampu meningkatkan kualitas
maupun kuantitas berbagai industri. Teknologi robotika juga telah menjangkau
sisi hiburan dan pendidikan bagi manusia. Salah satu cara menambah tingkat
kecerdasan sebuah robot adalah dengan menambah sensor, metode kontrol bahkan
memberikan kecerdasan buatan pada robot tersebut. Salah satunya adalah self balancing robot.
Self balancing
robot (robot penyeimbang) merupakan suatu robot yang memiliki dua buah roda
disisi kanan dan kirinya yang tidak akan seimbang apabila tanpa adanya
kontroler. Balancing robot ini merupakan pengembangan dari model pendulum
terbalik (inverted pendulum) yang diletakkan di atas kereta beroda.
Menyeimbangkan robot beroda dua memerlukan suatu perangkaian hardware yang baik
dan metode kontrol handal untuk mempertahankan posisi robot dalam keadaan tegak
lurus terhadap permukaan bumi. Dan konsep self
balancing robot ini telah digunakan sebagai alat transportasi yang bernama segway.
Fungsi dan Tujuan
Fungsi dari
pembuatan robot balancing ini yaitu untuk dapat mengetahui bagaimana cara untuk
membuat suatu robot balancing dari proses pembuatan hardware, pembuatan
software, dan penyusunan hardware pada robot, untuk tujuan dari pembuatan robot
yaitu agar robot ini dapat dikembangkan keareh yang lebih bermanfaat bagi
manuisia terutama untuk membantu keseharian hidup manusia.
Desain Platform
Alat dan Bahan
1. Arduino
Uno
2. Motor
Driver
3. Gearbox
+ motor DC
4. Speser
8 buah
5. Power
Supply 9 V (2 buah)
6. Akrilik
7. Kabel
jumper
8. Modul
Gyro & Accelerator
SISTEM KONTROL
Flowchart
Gambar II-1. Flowchart Self Balancing Robot
Prinsip
kerja self balancing robot yaitu robot akan berusaha untuk menyeimbangkan
keadaan akan sudut kemiringan yang diterima, dan juga robot bergerak maju dan
mundur untuk mendapatkan titik keseimbangan.robot ini menggunakan system
mikrokontroler arduino sebagai otak dan pusat kendali robot. Robot ini juga
menggunakan sensor kemiringan yaitu sensor accelerometer , yang mana sensor ini
bisa mendeteksi kemiringan sumbu X, sumbu Y dan sumbu Z, dengan range atau
panjang nilai setiap sumbu yaitu 1 sampai 5. Keseimbangannya, maka robot akan
diam sejenak dan berusaha untuk tidak jatuh.
Blok Diagram Sistem
Gambar II-2. Blok Diagram Sistem
Pada
sistem yang masuk berupa sensor accelerometer sebagai mata dari robot, yang
mana data dari sensor akan dikirimkan ke mikrokontroler untuk diolah sehingga
mendapatkan nilai.
SISTEM ALAT
Wiring System
Gambar III-1. Wiring System
Spesifikasi Alat
1. Arduino Uno
Arduino UNO adalah sebuah board mikrokontroler
yang didasarkan pada ATmega328 (datasheet). Arduino UNO mempunyai 14 pin digital
input/output (6 di antaranya dapat digunakan sebagai output PWM), 6 input
analog, sebuah osilator Kristal 16 MHz, sebuah koneksi USB, sebuah power jack,
sebuah ICSP header, dan sebuat tombol reset. Arduino UNO memuat semua yang
dibutuhkan untuk menunjang mikrokontroler, mudah menghubungkannya ke sebuah
computer dengan sebuah kabel USB atau mensuplainya dengan sebuah adaptor AC ke
DC atau menggunakan baterai untuk memulainya.Arduino Uno berbeda dari semua
board Arduino sebelumnya, Arduino UNO tidak menggunakan chip driver FTDI
USB-to-serial. Sebaliknya, fitur-fitur Atmega16U2 (Atmega8U2 sampai ke versi
R2) diprogram sebagai sebuah pengubah USB ke serial.
Gambar III-2. Arduino Uno
2. Motor Driver
L298 adalah jenis IC driver motor yang dapat
mengendalikan arah putaran dan kecepatan motor DC ataupun Motor stepper. Mampu
mengeluarkan output tegangan untuk Motor dc dan motor stepper sebesar 50 volt.
IC l298 terdiri dari transistor-transistor logik (TTL) dengan gerbang nand yang
memudahkan dalam menentukkan arah putaran suatu motor dc dan motor stepper.
Dapat mengendalikan 2 untuk motor dc namun pada hanya dapat mengendalikan 1
motor stepper. Penggunaannya paling sering untuk robot line follower. Bentuknya
yang kecil memungkinkan dapat meminimalkan pembuatan robot line follower.
Gambar III-3 Motor Driver L298N
3. Gearbox
Gearbox atau transmisi adalah salah satu komponen
utama motor yang disebut sebagai sistem pemindah tenaga, transmisi berfungsi
untuk memindahkan dan mengubah tenaga dari motor yang berputar, yang digunakan
untuk memutar spindel mesin maupun melakukan gerakan feeding. Motor DC adalah motor
listrik yang memerlukan suplai tegangan arus searah pada kumparan medan untuk
diubah menjadi energi gerak mekanik. Kumparan medan pada motor dc disebut stator (bagian yang tidak berputar) dan kumparan jangkar
disebut rotor (bagian yang berputar).
Gambar III-4. Gearbox
4. Modul Gyro & Accelerometer
Accelerometer
Merupakan sensor
berfungsi untuk mengukur percepatan suatu benda atau objek yang bergerak yang
bersifat dynamic maupun static. Dan gyroscope merupakan sensor
yang berfungsi untuk menentukan orientasi gerak dengan bertumpu pada roda
yang berotasi dengan cepat pada sumbu yang berdasarkan momentum sudut.
Gambar III-5. Modul Gyro & Accelerometer
5. Baterai
Power
supply yang digunakan pada Self
balancing robot ini ada 2 jenis yaitu baterai 9 volt
yang terhubung ke arduino
dan adapter 12v yang
terhubung ke motor driver.
Gambar III-6. Baterai 9 Volt
SOFTWARE
• Sistem Kontrol PID ( Proportional–Integral–Derivative
controller) merupakankontroler untuk menentukan presisi suatu sistem
instrumentasi dengan karakteristik
• adanya umpan balik pada sistem tesebut (Feed back),
mengingat balancing robotadalah sebuah sistem yang membutuhkan presisi dan
menekan noise sekecil mungkin dari
bias pergerkan robot tersebut
• maka penggunaan kontrol PID sangat dibutuhkan agar aksi yang dilakukan lebih presisi dan lebih halus
sehingga noise dari bias
• pergerakan robot dapat diminimalisir dan kecepatan dan
arah yang dilakukan sesuai dengan error sudut robot.
• Sistem kontrol PID terdiri dari tiga buah cara
pengaturan yaitu kontrol P(Proportional), D (Derivative) dan I (Integral),
dengan masing-masing memiliki kelebihan dan kekurangan.
• Dalam implementasinya masing-masing cara dapat bekerja
sendiri maupun gabungan diantaranya.
• Dalam perancangan sistem control PID yang perlu
dilakukan adalah mengatur parameter P, I atau D agar tanggapan sinyal keluaran
system terhadap masukan tertentu sebagaimana yang diinginkan
Source Code
#include <PID_v1.h> // library pid
#include <LMotorController.h> // library motor driver
#include "I2Cdev.h" //metode komunikasi sensor
#include "MPU6050_6Axis_MotionApps20.h" //library mpu6050
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
#define MIN_ABS_SPEED 30
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
//PID
double originalSetpoint = 172.60; //berdasar perubahan sudut
double setpoint = originalSetpoint;
double movingAngleOffset = 0.1;
double input, output;
//input PID berdasarkan kemiringan
double Kp = 60;
double Kd = 2.2;
double Ki = 270;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);
double motorSpeedFactorLeft = 0.6; //kecepatan motor
double motorSpeedFactorRight = 0.5;
//MOTOR CONTROLLER
int ENA = 5;
int IN1 = 6;
int IN2 = 7;
int IN3 = 9;
int IN4 = 8;
int ENB = 10;
LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, motorSpeedFactorLeft, motorSpeedFactorRight);
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)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
mpu.initialize();
devStatus = mpu.dmpInitialize();
// gyro offsets , scaled for min sensitivity
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
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
mpu.setDMPEnabled(true);
// 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.SetMode(AUTOMATIC);
pid.SetSampleTime(10);
pid.SetOutputLimits(-255, 255);
}
else
{
// ERROR!
// 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 "));
Serial.print(devStatus);
Serial.println(F(")"));
}
}
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
pid.Compute();
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
mpu.resetFIFO();
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;
}
}
#include <LMotorController.h> // library motor driver
#include "I2Cdev.h" //metode komunikasi sensor
#include "MPU6050_6Axis_MotionApps20.h" //library mpu6050
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
#define MIN_ABS_SPEED 30
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
//PID
double originalSetpoint = 172.60; //berdasar perubahan sudut
double setpoint = originalSetpoint;
double movingAngleOffset = 0.1;
double input, output;
//input PID berdasarkan kemiringan
double Kp = 60;
double Kd = 2.2;
double Ki = 270;
PID pid(&input, &output, &setpoint, Kp, Ki, Kd, DIRECT);
double motorSpeedFactorLeft = 0.6; //kecepatan motor
double motorSpeedFactorRight = 0.5;
//MOTOR CONTROLLER
int ENA = 5;
int IN1 = 6;
int IN2 = 7;
int IN3 = 9;
int IN4 = 8;
int ENB = 10;
LMotorController motorController(ENA, IN1, IN2, ENB, IN3, IN4, motorSpeedFactorLeft, motorSpeedFactorRight);
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)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
mpu.initialize();
devStatus = mpu.dmpInitialize();
// gyro offsets , scaled for min sensitivity
mpu.setXGyroOffset(220);
mpu.setYGyroOffset(76);
mpu.setZGyroOffset(-85);
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
mpu.setDMPEnabled(true);
// 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.SetMode(AUTOMATIC);
pid.SetSampleTime(10);
pid.SetOutputLimits(-255, 255);
}
else
{
// ERROR!
// 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 "));
Serial.print(devStatus);
Serial.println(F(")"));
}
}
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
pid.Compute();
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
mpu.resetFIFO();
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;
}
}
0 Response to "Self Balancing Robot"
Post a Comment