Lompat ke konten Lompat ke sidebar Lompat ke footer

Cara Menggunakan MPU-6050 GY-521 Pada Arduino

Pengertian Sensor Gyroscope dan Accelerometer

Cara Menggunakan MPU-6050 GY-521 Arduino – MPU 6050 merupakan chip yang memiliki fungsi sebagai gyroscope dan accelerometer. Namun, apa perbedaaan gyroscope dan accelerometer tersebut?

Gyroscope adalah perangkat yang menggunakan gravitasi bumi yang berfungsi untuk menentukan rotasi (perputaran). Contoh penggunaan pada smartphone adalah kompas.

Accelerometer adalah perangkat yang tidak menggunakan gravitasi bumi yang berfungsi untuk menentukan orientasi (arah). Contoh penggunaan pada smartphone adalah mengganti wallpaper hanya dengan gerakan.

Berdasarkan datasheet dari chip MPU-6050, sensor ini terdiri dari 6 axis perangkat pelacakan gerakan.

3 axis untuk gyroscope dan 3 axis untuk accelerometer. Sensor ini menggunakan protokol I2C untuk berkomunikasi dengan mikrokontroller, namun berbeda dengan keluarganya MPU-6000 menggunakan I2C dan SPI.

Sensor ini menggunakan 16-bit ADC untuk mendigitalkan sinyal dari gyroscope dan accelerometer. Tegangan operasi chip ini hanya 2.375V hingga 3.46V.

GY-521 merupakan modul yang berisikan chip MPU-6050 yang telah terintegrasi ic regulator 5V, sehingga dapat menggunakan tegangan 5V.


Library MPU6050 GY521

Untuk dapat menggunakan modul MPU-6050 GY-521 Arduino ini, kita butuh tiga library. Namanya I2Cdev, MPU6050 dan Average. Silahkan teman-teman download ketiga library berikut:


dan


dan




Jika sudah di download, masukkan library tersebut kedalam arduino IDE dengan cara:

- Buka Arduino IDE
- Klik Sketch > Include Library > Add .ZIP Library
- Pilih library yang telah didownload.
- Kik Ok


Rangkaian MPU6050 GY521

Silahkan teman-teman mengikuti rangkaian MPU-6050 GY-521 Arduino pada gambar berikut:

Program MPU6050 GY521

Dibawah ini sudah saya siapkan program dengan kalibrasi otomatis.

// I2C device class (I2Cdev) demonstrasi sketsa Arduino untuk chip MPU6050
// 10/7/2011 oleh Jeff Rowberg <jeff@rowberg.net>
// Pembaruan harus (semoga) selalu tersedia di https://github.com/jrowberg/i2cdevlib
//
// Changelog:
// 2013-05-08 - menambahkan beberapa format output
// - menambahkan dukungan Fastwire tanpa batas
// 2011-10-07 - rilis awal

/* ==========================================
  Kode pustaka perangkat I2Cdev ini dibawah lisensi MIT
  Hak Cipta (c) 2011 Jeff Rowberg

  Izin dengan ini diberikan, gratis, kepada siapa pun yang mendapatkan salinannya
  perangkat lunak ini dan file-file dokumentasi terkait ("Perangkat Lunak"), untuk ditangani
  dalam Perangkat Lunak tanpa batasan, termasuk tanpa batasan hak
  untuk menggunakan, menyalin, memodifikasi, menggabungkan, menerbitkan, mendistribusikan, mensublisensikan, dan / atau menjual
  salinan Perangkat Lunak, dan untuk mengizinkan orang kepada siapa Perangkat Lunak ini berada
  diperlengkapi untuk melakukannya, tunduk pada ketentuan berikut:

  Pemberitahuan hak cipta di atas dan pemberitahuan izin ini harus disertakan dalam
  semua salinan atau bagian substansial Perangkat Lunak.

  PERANGKAT LUNAK INI DISEDIAKAN "SEBAGAIMANA ADANYA", TANPA JAMINAN APA PUN, BAIK TERSURAT MAUPUN
  DITERAPKAN, TAPI TIDAK TERBATAS PADA JAMINAN DAGANG,
  KESESUAIAN UNTUK TUJUAN TERTENTU DAN NONINFRINGEMENT. DALAM HAL TIDAK AKAN
  PENULIS ATAU PEMEGANG HAK CIPTA BERTANGGUNG JAWAB ATAS KLAIM, KERUSAKAN ATAU LAINNYA
  KEWAJIBAN, APAKAH DALAM TINDAKAN KONTRAK, TORT ATAU LAINNYA,
  DI LUAR ATAU DALAM HUBUNGAN DENGAN PERANGKAT LUNAK ATAU PENGGUNAAN ATAU HUBUNGAN LAIN DI
  PERANGKAT LUNAK.
  ===============================================
*/

// ================================================
// ========== Cara menyempurnakan nilai============
// ================================================
// Jika ingin kalibrasi lebih akurat,  nilai kalibrasi
// harus mendekati nol maka 2 perubahan harus dilakukan di bagian #define di bawah ini.
// AccStepSize atau GyroStepSize harus dikurangi. misalnya AccStepSize
// secara default 0.2 dapat diubah ke 0.1.
// perubahan kedua harus menjadi nilai "AllowRange" harus diturunkan ke rentang yang dapat diterima
// seperti 50 atau 10.

// ===============================================================
// ================= Format Output Dipilih di sini ===============
// ===============================================================
// batalkan komentar "OUTPUT_READABLE_QUATERNION" jika Anda ingin melihat nilai yang sebenarnya
// komponen angka empat dalam format [w, x, y, z] (bukan yang terbaik untuk parsing
// pada remote host seperti Processing atau apalah)
//#define OUTPUT_READABLE_QUATERNION

// batalkan komentar "OUTPUT_READABLE_EULER" jika Anda ingin melihat sudut Euler
// (dalam derajat) dihitung dari angka empat yang berasal dari FIFO.
// Perhatikan bahwa sudut Euler ini contohnya ada pada gimbal (untuk info lebih lanjut, lihat
// http://en.wikipedia.org/wiki/Gimbal_lock)
//#define OUTPUT_READABLE_EULER

// batalkan komentar "OUTPUT_READABLE_YAWPITCHROLL" jika Anda ingin melihat yaw /
// sudut pitch / roll (dalam derajat) dihitung dari angka empat yang datang
// dari FIFO. Catatan ini juga membutuhkan perhitungan vektor gravitasi.
// Perhatikan juga bahwa sudut yaw / pitch / roll yang ada pada gimbal (untuk
// info lebih lanjut, lihat: http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_YAWPITCHROLL

// batalkan komentar "OUTPUT_READABLE_REALACCEL" jika Anda ingin melihat akselerasi
// Kerangka referensi percepatan ini adalah
// tidak dikompensasi untuk orientasi, jadi + X selalu + X sesuai dengan
// sensor, hanya saja tanpa efek gravitasi. Jika Anda menginginkan akselerasi
// dikompensasi untuk orientasi, pilihlah OUTPUT_READABLE_WORLDACCEL.
//#define OUTPUT_READABLE_REALACCEL

// batalkan komentar "OUTPUT_READABLE_WORLDACCEL" jika Anda ingin melihat akselerasi
// komponen dengan gravitasi dihapus dan disesuaikan untuk kerangka dunia
// referensi (relatif terhadap orientasi awal, karena tidak ada magnetometer
// hadir dalam kasus ini). Bisa sangat berguna dalam beberapa kasus.
//#define OUTPUT_READABLE_WORLDACCEL
//=================================================================

// ================================================================
// ============================== Sertakan File ===================
// ================================================================
// I2Cdev dan MPU6050 harus diinstal sebagai pustaka, atau file .cpp / .h yang lain
// untuk kedua kelas harus berada di jalur sertakan proyek Anda
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#include "MPU6050.h"
#include "Average.h"
//=================================================================

// ===============================================================
// =============== I2c komunikasi serial Tentukan ================
// ===============================================================
// Pustaka Arduino Wire diperlukan jika implementasi I2Cdev I2CDEV_ARDUINO_WIRE
// digunakan di I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
//================================================================

//===============================================================
//==          Umum + Definisi terkait kalibrasi           ===
//===============================================================
#define ModeRange 100
#define StabilityTime 25000 //25 seconds, could be 40secs, only for dmp
#define LED_PIN 13
#define LED_PIN2 8
#define AllowedRange 150    // ini adalah nilai dalam rentang nol putaran yang dapat diterima dan tidak ada kalibrasi sumbu yang dilakukan.
#define GyroStepSize  1
#define AccStepSize  0.2 // nilai ini bisa lebih rendah ke 0,1 untuk mendapatkan data yang dikalibrasi lebih dekat ke nol tetapi kemudian kalibrasi akan membutuhkan lebih banyak waktu
#define MaxIncVal 10
//=================================================================

//===============================================================
//==            Deklarasi objek MPU6050                   ===
//===============================================================
// alamat I2C standar adalah 0x68
// alamat I2C tertentu dapat diteruskan sebagai parameter di sini
// Jika tegangan pada AD0 rendah = 0x68 (default untuk papan evaluasi InvenSense)
// Jika tegangan pada AD0 tinggi = 0x69
MPU6050 mpu;
//MPU6050 accelgyro(0x69); // <-- Digunakan tegangan AD0 tinggi
//==============================================================

//==============================================================
//=====             Variabel terkait DMP                   =====
//==============================================================
bool dmpReady = false;  // tetapkan true jika DMP init berhasil
uint8_t mpuIntStatus;   // memegang byte status interupsi aktual dari MPU
uint8_t devStatus;      // mengembalikan status setelah setiap operasi perangkat (0 = berhasil,!0 = jika ada kesalahan)
uint16_t packetSize;    // ukuran paket DMP yang diharapkan (standarnya adalah 42 byte)
uint16_t fifoCount;     // hitung semua byte saat ini di FIFO
uint8_t fifoBuffer[64]; // Buffer penyimpanan FIFO
//===============================================================

//===============================================================
//==             Variabel terkait keluaran data               ===
//===============================================================
// orientasi / gerakan vars
Quaternion q;           // [w, x, y, z]        wadah quaternion
#if defined(OUTPUT_READABLE_WORLDACCEL) || defined(OUTPUT_READABLE_REALACCEL)
VectorInt16 aa;         // [x, y, z]            accel pengukuran sensor
#endif

#if defined(OUTPUT_READABLE_WORLDACCEL) || defined(OUTPUT_READABLE_REALACCEL)
VectorInt16 aaReal;     // [x, y, z]            pengukuran sensor accel bebas gravitasi
#endif

#ifdef OUTPUT_READABLE_WORLDACCEL
VectorInt16 aaWorld;    // [x, y, z]            pengukuran sensor accel dunia-frame
#endif

#if defined(OUTPUT_READABLE_WORLDACCEL) || defined(OUTPUT_READABLE_REALACCEL) || defined(OUTPUT_READABLE_YAWPITCHROLL)
VectorFloat gravity;    // [x, y, z]            vektor grafitasi
#endif

#ifdef OUTPUT_READABLE_EULER
float euler[3];         // [psi, theta, phi]    Wadah sudut Euler
#endif

#ifdef OUTPUT_READABLE_YAWPITCHROLL
float ypr[3];           // [yaw, pitch, roll]   wadah yaw / pitch / roll dan vektor gravitasi
#endif
//===============================================================
//===============================================================
//=====              Prototipe fungsi                       =====
//===============================================================

int16_t getValue(char , char, MPU6050); //lihat definisi fungsi untuk detailnya
bool autocalibrate(char , char, MPU6050);
void SetXAccelOffset(MPU6050, int16_t);
void SetYAccelOffset(MPU6050, int16_t);
void SetZAccelOffset(MPU6050, int16_t);
void SetXGyroOffset(MPU6050, int16_t);
void SetYGyroOffset(MPU6050, int16_t);
void SetZGyroOffset(MPU6050, int16_t);
//================================================================
// ===============================================================
// ======              ROUTINE DETEKSI INTERRUPT             =====
// ===============================================================

volatile bool mpuInterrupt = false;     //menunjukkan apakah pin interupsi MPU sudah tinggi
void dmpDataReady() {
  mpuInterrupt = true;
}

// ================================================================

// ================================================================
// ======              Variabel Umum                          =====
// ================================================================
char DataFlowBreak;
int16_t CurTempM; //untuk pembacaan suhu sensor ini
unsigned long currentMillis;
bool waitstatus = false;
Average<int16_t> Mode(ModeRange);
bool blinkState = false;
//=====================================================================

void setup() {
  // bergabung dengan bus I2C (perpustakaan I2Cdev tidak melakukan ini secara otomatis)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif

  Serial.begin(115200);

  // inisialisasi perangkat
  Serial.println("Inisialisasi perangkat I2C...");
  mpu.initialize();

  // verifikasi koneksi
  Serial.println("Mencoba koneksi ke perangkat...");
  Serial.println(mpu.testConnection() ? "Koneksi MPU6050 sukses" : "Koneksi MPU6050 gagal");
  Serial.println("Kalibrari dimulai...");
  Serial.println("Kalibrasi Gyroscope");

  if (autocalibrate('g', 'X', mpu)) {
    Serial.println("Gyro X axis OK");
  } else {
    Serial.println("Gyro X axis GAGAL");
  }

  if (autocalibrate('G', 'y', mpu)) {
    Serial.println("Gyro Y axis OK");
  } else {
    Serial.println("Gyro Y axis GAGAL");
  }

  if (autocalibrate('g', 'Z', mpu)) {
    Serial.println("Gyro Z axis OK");
  } else {
    Serial.println("Gyro Z axis GAGAL");
  }

  Serial.println("Kalibrasi Accelerometer");

  if (autocalibrate('a', 'x', mpu)) {
    Serial.println("Accel X axis OK");
  } else {
    Serial.println("Accel X axis GAGAL");
  }

  if (autocalibrate('A', 'Y', mpu)) {
    Serial.println("Accel Y axis OK");
  } else {
    Serial.println("Accel Y axis GAGAL");
  }

  if (autocalibrate('A', 'Z', mpu)) {
    Serial.println("Accel Z axis OK");
  } else {
    Serial.println("Accel Z axis GAGAL");
  }

  Serial.println(F("Inisialisasi DMP...")); //Digital Motion Processor
  devStatus = mpu.dmpInitialize();

  // pastikan itu bekerja (kembalikan 0 jika demikian)
  if (devStatus == 0) {
    Serial.println(F("Aktifkan DMP..."));
    mpu.setDMPEnabled(true);
    currentMillis = millis();
    Serial.println(F("Aktifkan deteksi interrupt  (Arduino external interrupt 0)..."));
    attachInterrupt(0, dmpDataReady, RISING);
    mpuIntStatus = mpu.getIntStatus();

    Serial.println(F("DMP siap! menunggu untuk interrupt pertama..."));
    dmpReady = true;

    packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
    Serial.print(F("DMP Initialization failed (code "));
    Serial.print(devStatus);
    Serial.println(F(")"));
  }

  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  while (1) {
    if (!dmpReady) {
      continue;

    }

    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // dapatkan hitungan FIFO saat ini
    fifoCount = mpu.getFIFOCount();

    // periksa overflow (ini seharusnya tidak pernah terjadi kecuali kode kami terlalu tidak efisien)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
      // reset agar kita bisa melanjutkan dengan bersih
      mpu.resetFIFO();
      Serial.println(F("FIFO melimpah!"));

      // jika tidak, periksa data DMP siap interupsi (ini harus sering terjadi)
    } else if (mpuIntStatus & 0x02) {
      // tunggu panjang data yang tersedia benar, harus menunggu SANGAT singkat
      while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

      // baca paket dari FIFO
      mpu.getFIFOBytes(fifoBuffer, packetSize);

      // lacak jumlah FIFO di sini jika ada> 1 paket yang tersedia
      // ini memungkinkan kita segera membaca lebih banyak tanpa harus menunggu interupsi
      fifoCount -= packetSize;

#ifdef OUTPUT_READABLE_QUATERNION
      // tampilkan nilai angka empat dalam bentuk matriks mudah: w x y z
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      if ((millis() - currentMillis) <= StabilityTime)
      {
        if (waitstatus == false) {
          Serial.println("Mengunggu untuk stabilitas...");
          waitStatus = true;
        } else {
          
        }

      } else {
        Serial.print(millis() - currentMillis); Serial.print("\t");
        Serial.print("quat\t");
        Serial.print(q.w);
        Serial.print("\t");
        Serial.print(q.x);
        Serial.print("\t");
        Serial.print(q.y);
        Serial.print("\t");
        Serial.println(q.z);
      }

#endif

#ifdef OUTPUT_READABLE_EULER
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetEuler(euler, &q);
      if ((millis() - currentMillis) <= StabilityTime)
      {
        if (waitstatus == false) {
          Serial.println("Menunggu untuk stabilitas...");
          waitStatus = true;
        } else {
          
        }

      } else {
        Serial.print(millis() - currentMillis); Serial.print("\t");
        Serial.print("euler\t");
        Serial.print(euler[0] * 180 / M_PI);
        Serial.print("\t");
        Serial.print(euler[1] * 180 / M_PI);
        Serial.print("\t");
        Serial.println(euler[2] * 180 / M_PI);
      }
#endif

#ifdef OUTPUT_READABLE_YAWPITCHROLL
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
      if ((millis() - currentMillis) <= StabilityTime)
      {
        if (waitstatus == false) {
          Serial.println("Menunggu untuk stabilitas...");
          waitstatus = true;
        } else {
          
        }

      } else {
        Serial.print(millis() - currentMillis); Serial.print("\t");
        Serial.print("\t");
        Serial.print("ypr\t");
        Serial.print(ypr[0] * 180 / M_PI);
        Serial.print("\t");
        Serial.print(ypr[1] * 180 / M_PI);
        Serial.print("\t");
        Serial.println(ypr[2] * 180 / M_PI);
      }
#endif

#ifdef OUTPUT_READABLE_REALACCEL
      // tampilkan akselerasi nyata, disesuaikan untuk menghilangkan gravitasi
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetAccel(&aa, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
      if ((millis() - currentMillis) <= StabilityTime)
      {
        if (waitstatus == false) {
          Serial.println("Menunggu untuk stabilitas...");
          waitstatus = true;
        } else {
          
        }

      } else {
        Serial.print(millis() - currentMillis); Serial.print("\t");
        Serial.print("areal\t");
        Serial.print(aaReal.x);
        Serial.print("\t");
        Serial.print(aaReal.y);
        Serial.print("\t");
        Serial.println(aaReal.z);
      }
#endif

#ifdef OUTPUT_READABLE_WORLDACCEL
      // tampilkan akselerasi frame-dunia awal, disesuaikan untuk menghilangkan gravitasi
             // dan diputar berdasarkan orientasi yang diketahui dari quaternion
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetAccel(&aa, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
      mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);

      if ((millis() - currentMillis) <= StabilityTime)
      {
        if (waitstatus == false) {
          Serial.println("Menunggu untuk stabilitas...");
          waitstatus = true;
        } else {
          
        }

      } else {
        Serial.print(millis() - currentMillis); Serial.print("\t");
        Serial.print("aworld\t");
        Serial.print(aaWorld.x);
        Serial.print("\t");
        Serial.print(aaWorld.y);
        Serial.print("\t");
        Serial.println(aaWorld.z);
      }
#endif

      if (Serial.available()) {
        DataFlowBreak = Serial.read();
        if (DataFlowBreak == 'x' || DataFlowBreak == 'X' ) // jika pengguna memasukkan x X loop keluar dan Arduino berhenti mengekstraksi menampilkan data dari mpu.
          break;
      }

      blinkState = !blinkState;
      digitalWrite(LED_PIN2, blinkState);
    } //stopping the loop here

  }
  while (1); // berhenti mengirim data dan masuk ke loop tak terbatas
}

// Tujuan dari fungsi ini adalah untuk mendapatkan nilai dari aliran data yang sangat variabel. Fungsi ini digunakan
// teknik mode untuk mendapatkan nilai yang sangat akurat. ModeRange didefinisikan sebagai jumlah maksimum nilai pada mode mana yang akan diterapkan
// di sini pengguna harus melewati a atau g untuk menunjukkan sensor, sumbu yang diperlukan yaitu xy z dan akhirnya objek mpu
// akan mengembalikan 0 jika argumen salah
int16_t getValue(char sensor, char axis, MPU6050 mpu ) {

  int ii;
  int16_t dummy1, dummy2, dummy3, dummy4, dummy5; //mengabaikan nilai-nilai
  int16_t Final;

  if (sensor != 'a' && sensor != 'A' && sensor != 'g' && sensor != 'G') { // jika pengguna memasukkan sesuatu kecuali A g atau G menghasilkan false
    return 0;
  } else if (axis != 'x' && axis != 'X' && axis != 'y' && axis != 'Y' && axis != 'z' && axis != 'Z') { // jika pengguna memasukkan sesuatu kecuali x X y Y z atau Z mengembalikan false
    return 0;
  }

  for (ii = 0; ii <= ModeRange; ii++) {

    switch (sensor) { // sensor bisa berupa accelerometer atau giroskop.
      case 'a'://acceleormeter adalah a or A
      case 'A':
        switch (axis) {

          case 'x': //axis x
          case 'X': //axis x
            mpu.getMotion6(&Final, &dummy1, &dummy2, &dummy3, &dummy4, &dummy5);
            break;
          case 'y': //axis y
          case 'Y': //axis Y
            mpu.getMotion6(&dummy1, &Final, &dummy2, &dummy3, &dummy4, &dummy5);
            break;

          case'z': //axis z
          case'Z': //axis Z
            mpu.getMotion6(&dummy1, &dummy2, &Final, &dummy3, &dummy4, &dummy5);
            break;
        }
        break;
      case 'g': //gyrometer adalah g atau G
      case 'G':
        switch (axis) {

          case 'x':
          case 'X':
            mpu.getMotion6(&dummy3, &dummy4, &dummy5, &Final, &dummy1, &dummy2);
            break;
          case 'y':
          case 'Y':
            mpu.getMotion6(&dummy3, &dummy4, &dummy5, &dummy1, &Final, &dummy2);
            break;

          case'z':
          case'Z':
            mpu.getMotion6(&dummy3, &dummy4, &dummy5, &dummy1, &dummy2, &Final);
            break;
        }

        break;
    }
    //delay(1);
    delayMicroseconds(500);// alasan utama untuk menggunakan mikrodetik di sini adalah untuk mengurangi waktu yang dibutuhkan untuk kalibrasi
    Mode.push(Final);

  }
  Final = Mode.mode();

  return Final;
}

// Fungsi ini mencoba mengkalibrasi Accelerometer dan Giroskop secara otomatis dan mengembalikan true jika operasi berhasil
// Fungsi ini mengambil dalam 3 argumen 1 adalah sensor ('a' / 'A' = Accelerometer dan 'g' / 'G' = Giroskop), maka argumen ke-2 adalah sumbu untuk claibrate ('X' / 'x', 'Y' / 'y', 'Z' / 'z')
// dan argumen terakhir yang digunakan fungsi ini adalah objek mpu6050 yang dibuat.
bool autocalibrate(char sensor, char axis, MPU6050 mpu) {
  float n = 1;
  int16_t initalvalue;
  int16_t calibrateValue;
  int16_t firstoutput, secondoutput;
  void (*FuncPointerToSetOffset)(MPU6050, int16_t);
  float stepsize = 0.5;
  if (sensor != 'a' && sensor != 'A' && sensor != 'g' && sensor != 'G') { //if user enters anything except a A g or G return false
    return false;
  } else if (axis != 'x' && axis != 'X' && axis != 'y' && axis != 'Y' && axis != 'z' && axis != 'Z') { //if user enters anything except x X y Y z or Z return false
    return false;
  }

  switch (sensor) { //sensor dapat menjadi accelerometer atau gyroscope.
    case 'a'://acceleormeter adalah a atau A
    case 'A':
      stepsize = AccStepSize;
      switch (axis)
      { case 'x': //axis x
        case 'X': //axis x

          FuncPointerToSetOffset =  SetXAccelOffset;
          break;
        case 'y':
        case 'Y':

          FuncPointerToSetOffset = SetYAccelOffset;
          break;

        case'z':
        case'Z':

          FuncPointerToSetOffset = SetZAccelOffset;
          break;
      }
      break;
    case 'g': //gyrometer is g or G
    case 'G':
      stepsize = GyroStepSize;
      switch (axis)
      { case 'x': //axis x
        case 'X': //axis x

          FuncPointerToSetOffset = SetXGyroOffset;
          break;
        case 'y':
        case 'Y':
          FuncPointerToSetOffset = SetYGyroOffset;
          break;

        case'z':
        case'Z':
          FuncPointerToSetOffset = SetZGyroOffset;
          break;
      }

      break;
  }
  calibrateValue = getValue(sensor, axis, mpu); // sensor (gyro / accl), sumbu (x y z) dan objek mpu

  if (abs(calibrateValue) <= AllowedRange ) // ketika Anda tidak perlu melakukan kalibrasi setelah semua. ketika data mendekati nol dalam rentang yang diijinkan (default 150)
    return true;


  initalvalue = calibrateValue * (-1); // inversi itu penting di sini.
  calibrateValue = initalvalue / n;
  FuncPointerToSetOffset(mpu, calibrateValue); // function pointer dengan argumen fungsi
  firstoutput = getValue(sensor, axis, mpu); // sensor (gyro / accl), sumbu (x y z) dan objek mpu

  while (n < 10) { // di sini 10 adalah pilihan acak dan 10 ini akan memastikan loop tidak berjalan selama lebih dari 50 loop (jika ukuran langkah adalah 0,2)
    n += stepsize;
    calibrateValue = initalvalue / n;
    FuncPointerToSetOffset(mpu, calibrateValue);
    secondoutput = getValue(sensor, axis, mpu); // sensor (gyro/accl), axis(x y z) and objek mpu
    // di sini kita periksa apakah nilai karena offset sebelumnya lebih dekat ke nol atau nilai akibat offset saat ini lebih dekat ke nol
    // Selain itu tanda nilai juga diperiksa yaitu saat perubahan kita berhenti (misalnya nilai beralih dari + ve ke -ve)
    if ( abs(firstoutput) < abs(secondoutput) && (firstoutput / abs(firstoutput) * secondoutput / abs(secondoutput)) != -1 ) {
      n = n - stepsize;
      FuncPointerToSetOffset(mpu , initalvalue / n); // kita atur nilai sebelumnya karena nilai saat ini lebih jauh dari tanda nol
      break;
    } else {
      firstoutput = secondoutput; // jika nilai saat ini lebih rendah dari nilai sebelumnya daripada kami memeriksa nilai berikutnya.
    }
  }

  return true;
} //end of function


// alasan pembuatan fungsi ini adalah bahwa fungsi pointer digunakan untuk menunjuk ke fungsi ini.
// function pointer tidak dapat menunjuk ke fungsi anggota statis dari suatu objek yang saya pikir. jadi fungsi ini harus digunakan.
// selain itu kita dapat menggunakan fungsi-fungsi ini untuk menambahkan pengurangan konstanta lain untuk kalibrasi offset seperti +16384 untuk Az dapat dimasukkan di sini.

void SetXAccelOffset(MPU6050 mpu , int16_t value) {

  mpu.setXAccelOffset(value);
}

void SetYAccelOffset(MPU6050 mpu , int16_t value) {

  mpu.setYAccelOffset(value);
}

void SetZAccelOffset(MPU6050 mpu , int16_t value) {

  mpu.setZAccelOffset(value);
}

void SetXGyroOffset(MPU6050 mpu , int16_t value) {

  mpu.setXGyroOffset(value);
}


void SetYGyroOffset(MPU6050 mpu , int16_t value) {

  mpu.setYGyroOffset(value);
}


void SetZGyroOffset(MPU6050 mpu , int16_t value) {

  mpu.setZGyroOffset(value);
}

Dari program di atas mendapatkan hasil seperti pada gambar dibawah.
Semoga bermanfaat.

Posting Komentar untuk "Cara Menggunakan MPU-6050 GY-521 Pada Arduino"