dianartanto

Self Balancing Robot

Apr 8th, 2026
35
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.48 KB | None | 0 0
  1. #include <PID_v2.h>
  2. #include "I2Cdev.h"
  3. #include "MPU6050.h"
  4. #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  5. #include "Wire.h"
  6. #endif
  7. #define motorA_IN1 6
  8. #define motorA_IN2 7
  9. #define motorA_ENA 11
  10. #define motorB_IN3 4
  11. #define motorB_IN4 5
  12. #define motorB_ENB 10
  13. MPU6050 mpu(0x68);
  14. double setpoint = 0;
  15. double input;
  16. double output;
  17. double kp = 40, ki = 0.8, kd = 1.2;
  18. PID balancePID(&input, &output, &setpoint, kp, ki, kd, DIRECT);
  19. unsigned long lastTime = 0;
  20. const int sampleTime = 10;
  21. void setup() {
  22.   Serial.begin(115200);
  23.   Serial.println("Self-Balancing Robot Starting...");
  24.   Wire.begin();
  25.   // Untuk LGT8F328 @32MHz, nilai TWBR 32 sangat penting agar I2C stabil
  26.   TWBR = 32;
  27.   delay(1000);
  28.   Serial.println("Initializing Sensor...");
  29.   // Membangunkan sensor secara manual (Wake up)
  30.   Wire.beginTransmission(0x68);
  31.   Wire.write(0x6B);
  32.   Wire.write(0);
  33.   Wire.endTransmission();
  34.   delay(100);
  35.   // Deklarasi variabel chipID di sini agar tidak error 'not declared'
  36.   byte chipID = 0;
  37.   // Membaca ID perangkat secara langsung dari register 0x75 (WHO_AM_I)
  38.   Wire.beginTransmission(0x68);
  39.   Wire.write(0x75);
  40.   Wire.endTransmission();
  41.   Wire.requestFrom(0x68, 1);
  42.   if (Wire.available()) {
  43.     chipID = Wire.read();
  44.     Serial.print("Device ID found: 0x");
  45.     Serial.println(chipID, HEX);
  46.   }
  47.   mpu.initialize();
  48.   // Modifikasi pengecekan koneksi: Izinkan ID 0x68 (MPU) atau 0x70 (QMI)
  49.   if (chipID == 0x68 || chipID == 0x70) {
  50.     Serial.println("Sensor connection successful");
  51.   } else {
  52.     Serial.println("Warning: Sensor connection failed or unknown ID");
  53.     // Kita tetap lanjut (tidak pakai while(1)) untuk mengetes apakah data terbaca
  54.     Serial.println("Attempting to proceed anyway...");
  55.   }
  56.   calibrateSensor();
  57.   pinMode(motorA_IN1, OUTPUT);
  58.   pinMode(motorA_IN2, OUTPUT);
  59.   pinMode(motorA_ENA, OUTPUT);
  60.   pinMode(motorB_IN3, OUTPUT);
  61.   pinMode(motorB_IN4, OUTPUT);
  62.   pinMode(motorB_ENB, OUTPUT);
  63.   balancePID.SetMode(AUTOMATIC);
  64.   balancePID.SetSampleTime(sampleTime);
  65.   balancePID.SetOutputLimits(-255, 255);
  66.   Serial.println("Initialization complete!");
  67. }
  68. double getBalanceAngle() {
  69.   static double gyroAngle = 0;
  70.   static unsigned long prevTime = 0;
  71.   int16_t ax, ay, az, gx, gy, gz;
  72.   mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  73.   double accelAngle = atan2(ax, az) * 180 / PI;
  74.   unsigned long currentTime = millis();
  75.   double dt = (currentTime - prevTime) / 1000.0;
  76.   prevTime = currentTime;
  77.   double gyroRate = gy / 131.0;
  78.   gyroAngle += gyroRate * dt;
  79.   double filteredAngle = 0.95 * gyroAngle + 0.05 * accelAngle;
  80.   gyroAngle = filteredAngle;  // Update gyro angle
  81.   return filteredAngle;
  82. }
  83. void setMotorSpeeds(int leftSpeed, int rightSpeed) {
  84.   leftSpeed = constrain(leftSpeed, -255, 255);
  85.   rightSpeed = constrain(rightSpeed, -255, 255);
  86.   if (leftSpeed >= 0) {
  87.     digitalWrite(motorA_IN1, HIGH);
  88.     digitalWrite(motorA_IN2, LOW);
  89.     analogWrite(motorA_ENA, leftSpeed);
  90.   } else {
  91.     digitalWrite(motorA_IN1, LOW);
  92.     digitalWrite(motorA_IN2, HIGH);
  93.     analogWrite(motorA_ENA, abs(leftSpeed));
  94.   }
  95.   if (rightSpeed >= 0) {
  96.     digitalWrite(motorB_IN3, HIGH);
  97.     digitalWrite(motorB_IN4, LOW);
  98.     analogWrite(motorB_ENB, rightSpeed);
  99.   } else {
  100.     digitalWrite(motorB_IN3, LOW);
  101.     digitalWrite(motorB_IN4, HIGH);
  102.     analogWrite(motorB_ENB, abs(rightSpeed));
  103.   }
  104. }
  105. void stopMotors() {
  106.   analogWrite(motorA_ENA, 0);
  107.   analogWrite(motorB_ENB, 0);
  108. }
  109. void loop() {
  110.   unsigned long currentTime = millis();
  111.   if (currentTime - lastTime >= sampleTime) {
  112.     lastTime = currentTime;
  113.     input = getBalanceAngle();
  114.     if (abs(input) > 45) {
  115.       stopMotors();
  116.       Serial.println("Robot fallen - stopping motors");
  117.       return;
  118.     }
  119.     balancePID.Compute();
  120.     int motorSpeed = (int)output;
  121.     setMotorSpeeds(motorSpeed, motorSpeed);
  122.     Serial.print("Angle: ");
  123.     Serial.print(input);
  124.     Serial.print(" | Output: ");
  125.     Serial.println(output);
  126.   }
  127. }
  128. void calibrateSensor() {
  129.   Serial.println("Calibrating sensor - hold robot vertical...");
  130.   long accelSum = 0, gyroSum = 0;
  131.   int samples = 1000;
  132.   for (int i = 0; i < samples; i++) {
  133.     int16_t ax, ay, az, gx, gy, gz;
  134.     mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  135.     accelSum += ax;
  136.     gyroSum += gy;
  137.     delay(3);
  138.   }
  139.   int accelOffset = accelSum / samples;
  140.   int gyroOffset = gyroSum / samples;
  141.   Serial.print("Calibration complete. Offsets - Accel: ");
  142.   Serial.print(accelOffset);
  143.   Serial.print(", Gyro: ");
  144.   Serial.println(gyroOffset);
  145. }
Advertisement
Comments
  • User was banned
Add Comment
Please, Sign In to add comment