Cara Menggunakan MPU-6050 GY-521 Pada Arduino
A. 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.
B. 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
C. Rangkaian MPU6050 GY521
Silahkan teman-teman mengikuti rangkaian MPU-6050 GY-521 Arduino pada gambar berikut:
D. 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); }
Post a Comment for "Cara Menggunakan MPU-6050 GY-521 Pada Arduino"