Dalam tutorial ini kita akan mempelajari cara mengukur sudut dan melacak orientasi menggunakan Arduino dan sensor Akselerometer ADXL345. Anda dapat menonton video berikut atau membaca tutorial tulisan di bawahnya untuk detail lebih lanjut.
Tinjauan Umum
Pertama, saya akan menjelaskan cara kerja sensor dan cara membaca data darinya, dan kemudian menggunakan lingkungan pengembangan Processing, kita akan membuat visualisasi 3D dari orientasi akselerometer.
Cara Kerja Akselerometer ADXL345
Untuk memulai, mari kita lihat bagaimana sensor ADXL345 bekerja. Ini adalah akselerometer 3-sumbu yang dapat mengukur gaya percepatan statis dan dinamis. Gaya gravitasi bumi adalah contoh typikal gaya statis, sementara gaya dinamis dapat disebabkan oleh getaran, gerakan, dan sebagainya.
Satuan pengukuran percepatan adalah meter per detik kuadrat (m/s^2). Namun, sensor akselerometer biasanya menyatakan pengukuran dalam "g" atau gravitasi. Satu "g" adalah nilai gaya gravitasi bumi yang sama dengan 9,8 meter per detik kuadrat.
Jadi, jika kita memiliki akselerometer yang diposisikan datar, dengan sumbu Z-nya menunjuk ke atas, berlawanan dengan gaya gravitasi, output sumbu Z dari sensor akan 1g. Di sisi lain, output X dan Y akan nol, karena gaya gravitasi tegak lurus terhadap sumbu ini dan tidak mempengaruhi mereka sama sekali.
Jika kita membalik sensor terbalik, maka output sumbu Z akan -1 g. Ini berarti output sensor karena orientasinya terhadap gravitasi dapat bervariasi dari -1g hingga +1g.
Jadi berdasarkan data ini dan menggunakan beberapa matematika trigonometri, kita dapat menghitung sudut di mana sensor diposisikan.
Cara Membaca Data Akselerometer ADXL345 dengan Arduino
Baik, sekarang mari kita lihat bagaimana kita dapat membaca data akselerometer ADXL345 menggunakan Arduino. Sensor ini menggunakan protokol I2C untuk komunikasi dengan Arduino jadi kita hanya perlu dua kabel untuk menghubungkannya, ditambah dua kabel untuk menyuntikkan daya.
Anda dapat mendapatkan komponen yang dibutuhkan untuk tutorial Arduino ini dari tautan di bawah ini:
Berikut adalah kode Arduino untuk membaca data akselerometer ADXL345.
/* Arduino and ADXL345 Accelerometer Tutorial by Dejan, https://howtomechatronics.com */ #include <Wire.h> // Wire library - used for I2C communication int ADXL345 = 0x53; // The ADXL345 sensor I2C address float X_out, Y_out, Z_out; // Outputs void setup() { Serial.begin(9600); // Initiate serial communication for printing the results on the Serial monitor Wire.begin(); // Initiate the Wire library // Set ADXL345 in measuring mode Wire.beginTransmission(ADXL345); // Start communicating with the device Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D // Enable measurement Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable Wire.endTransmission(); delay(10); } void loop() { // === Read acceleromter data === // Wire.beginTransmission(ADXL345); Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H) Wire.endTransmission(false); Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers X_out = ( Wire.read()| Wire.read() << 8); // X-axis value X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value Y_out = Y_out/256; Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value Z_out = Z_out/256; Serial.print("Xa= "); Serial.print(X_out); Serial.print(" Ya= "); Serial.print(Y_out); Serial.print(" Za= "); Serial.println(Z_out); }Code language: Arduino (arduino)
Deskripsi: Jadi pertama kita perlu menyertakan library Wire.h yang digunakan untuk komunikasi I2C. Jika Anda ingin mempelajari lebih lanjut bagaimana komunikasi I2C bekerja dan cara menggunakannya dengan Arduino Anda dapat memeriksa tutorial detail lainnya saya untuk itu.
Setiap perangkat yang menggunakan komunikasi I2C memiliki alamat I2C unik, dan alamat ini dapat ditemukan dalam datasheet sensor (Datasheet ADXL345). Jadi, setelah kita menentukan alamat dan variabel untuk tiga outputnya, pada bagian setup, pertama, kita perlu menginisialisasi library wire dan kemudian mengatur akselerometer ke mode pengukuran. Untuk melakukan itu, jika kita melihat kembali datasheet, kita dapat melihat bahwa kita perlu mengatur bit D3 dari register POWER_CTL menjadi HIGH.
Jadi, menggunakan fungsi beginTransmission() kita memulai komunikasi, kemudian menggunakan fungsi write() kita memberitahu register mana yang ingin kita akses, dan lagi menggunakan fungsi write() kita mengatur bit D3 menjadi HIGH, dengan menulis angka 8 dalam desimal yang sesuai dengan mengatur bit D3 menjadi HIGH.
// Set ADXL345 in measuring mode Wire.beginTransmission(ADXL345); // Start communicating with the device Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D // Enable measurement Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable Wire.endTransmission();Code language: Arduino (arduino)
Pada bagian loop sekarang kita membaca data dari sensor. Data untuk setiap sumbu disimpan dalam dua byte atau register. Kita dapat melihat alamat register ini dari datasheet.
Untuk membacanya semua, kita mulai dengan register pertama, dan menggunakan fungsi requestionFrom() kita meminta untuk membaca 6 register. Kemudian menggunakan fungsi read(), kita membaca data dari setiap register, dan karena outputnya adalah komplement dua kita menggabungkannya dengan tepat untuk mendapatkan nilai yang benar.
// === Read acceleromter data === // Wire.beginTransmission(ADXL345); Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H) Wire.endTransmission(false); Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers X_out = ( Wire.read()| Wire.read() << 8); // X-axis value X_out = X_out/256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet Y_out = ( Wire.read()| Wire.read() << 8); // Y-axis value Y_out = Y_out/256; Z_out = ( Wire.read()| Wire.read() << 8); // Z-axis value Z_out = Z_out/256;Code language: Arduino (arduino)
Nilai output dari sensor sebenarnya bergantung pada sensitivitas yang dipilih, yang dapat bervariasi dari +- 2g hingga +-16g. Sensitivitas default adalah +-2g jadi itulah sebabnya kita perlu membagi output dengan 256 untuk mendapatkan nilai dari -1 hingga +1g. 256 LSB/g berarti kita memiliki 256 hitungan per g.
Bergantung pada aplikasi kita dapat memilih sensitivitas yang sesuai. Dalam kasus ini, untuk pelacakan orientasi, sensitivitas +-2g sudah cukup, tetapi untuk aplikasi di mana kita perlu merasakan gaya percepatan yang lebih tinggi seperti gerakan tiba-tiba, kejutan, dan sebagainya, kita dapat memilih salah satu rentang sensitivitas lainnya menggunakan register DATA_FORMAT dan bit D1 dan D0-nya.
Kalibrasi Akselerometer ADXL345
Namun, setelah kita membaca data, kita dapat dengan mencetaknya pada serial monitor untuk memeriksa apakah nilainya seperti yang diharapkan. Dalam kasus saya, nilai yang saya peroleh tidak persis seperti yang seharusnya, terutama sumbu Z yang memiliki kesalahan yang terlihat sebesar 0.1g.
Untuk mengatasi masalah ini, kita perlu mengkalibrasi akselerometer menggunakan 3 register kalibrasi offset, dan berikut adalah cara melakukannya. Jadi, kita perlu memosisikan sensor datar, dan mencetak nilai RAW tanpa membaginya dengan 256.
Dari sini sekarang kita dapat melihat seberapa besar outputnya menyimpang, dalam kasus saya, output Z sekitar 283. Itu adalah selisih 27 dalam positif. Sekarang kita perlu membagi nilai ini dengan 4, dan itu akan memberikan angka yang kita butuhkan untuk ditulis ke register offset sumbu Z. Jika kita mengunggah kode sekarang, output sumbu Z akan persis 256, atau 1g seperti yang seharusnya.
Jika diperlukan kita harus mengkalibrasi sumbu lainnya menggunakan metode yang sama. Dan hanya catatan cepat bahwa kalibrasi ini tidak ditulis secara permanen ke register. Kita perlu menulis nilai-nilai ini ke register pada setiap pemasangan daya sensor.
Setelah selesai dengan kalibrasi, kita sekarang dapat akhirnya menghitung Roll dan Pitch, atau rotasi di sekitar sumbu X dan rotasi di sekitar sumbu Y dalam derajat, menggunakan dua rumus ini.
// Calculate Roll and Pitch (rotation around X-axis, rotation around Y-axis) roll = atan(Y_out / sqrt(pow(X_out, 2) + pow(Z_out, 2))) * 180 / PI; pitch = atan(-1 * X_out / sqrt(pow(Y_out, 2) + pow(Z_out, 2))) * 180 / PI;Code language: Arduino (arduino)
Untuk detail lebih lanjut bagaimana rumus ini bekerja, Anda dapat memeriksa catatan aplikasi Freescale Semiconductor ini.
Arduino dan Akselerometer ADXL345 Pelacakan Orientasi – Visualisasi 3D
Baik, mari kita buat contoh visualisasi 3D akselerometer sekarang.
Jadi, kita menggunakan kode yang sama, yang mengirim nilai Roll dan Pitch melalui port serial. Berikut adalah kode Arduino lengkap:
/* Arduino and ADXL345 Accelerometer - 3D Visualization Example by Dejan, https://howtomechatronics.com */ #include <Wire.h> // Wire library - used for I2C communication int ADXL345 = 0x53; // The ADXL345 sensor I2C address float X_out, Y_out, Z_out; // Outputs float roll,pitch,rollF,pitchF=0; void setup() { Serial.begin(9600); // Initiate serial communication for printing the results on the Serial monitor Wire.begin(); // Initiate the Wire library // Set ADXL345 in measuring mode Wire.beginTransmission(ADXL345); // Start communicating with the device Wire.write(0x2D); // Access/ talk to POWER_CTL Register - 0x2D // Enable measurement Wire.write(8); // Bit D3 High for measuring enable (8dec -> 0000 1000 binary) Wire.endTransmission(); delay(10); //Off-set Calibration //X-axis Wire.beginTransmission(ADXL345); Wire.write(0x1E); Wire.write(1); Wire.endTransmission(); delay(10); //Y-axis Wire.beginTransmission(ADXL345); Wire.write(0x1F); Wire.write(-2); Wire.endTransmission(); delay(10); //Z-axis Wire.beginTransmission(ADXL345); Wire.write(0x20); Wire.write(-9); Wire.endTransmission(); delay(10); } void loop() { // === Read acceleromter data === // Wire.beginTransmission(ADXL345); Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H) Wire.endTransmission(false); Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers X_out = ( Wire.read() | Wire.read() << 8); // X-axis value X_out = X_out / 256; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet Y_out = ( Wire.read() | Wire.read() << 8); // Y-axis value Y_out = Y_out / 256; Z_out = ( Wire.read() | Wire.read() << 8); // Z-axis value Z_out = Z_out / 256; // Calculate Roll and Pitch (rotation around X-axis, rotation around Y-axis) roll = atan(Y_out / sqrt(pow(X_out, 2) + pow(Z_out, 2))) * 180 / PI; pitch = atan(-1 * X_out / sqrt(pow(Y_out, 2) + pow(Z_out, 2))) * 180 / PI; // Low-pass filter rollF = 0.94 * rollF + 0.06 * roll; pitchF = 0.94 * pitchF + 0.06 * pitch; Serial.print(rollF); Serial.print("/"); Serial.println(pitchF); }Code language: Arduino (arduino)
Sekarang di lingkungan pengembangan Processing kita perlu menerima nilai-nilai ini dan menggunakannya untuk memutar objek 3D yang akan kita buat. Berikut adalah kode Processing lengkap:
/* Arduino and ADXL345 Accelerometer - 3D Visualization Example by Dejan, https://howtomechatronics.com */ import processing.serial.*; import java.awt.event.KeyEvent; import java.io.IOException; Serial myPort; String data=""; float roll, pitch; void setup() { size (960, 640, P3D); myPort = new Serial(this, "COM8", 9600); // starts the serial communication myPort.bufferUntil('\n'); } void draw() { translate(width/2, height/2, 0); background(33); textSize(22); text("Roll: " + int(roll) + " Pitch: " + int(pitch), -100, 265); // Rotate the object rotateX(radians(roll)); rotateZ(radians(-pitch)); // 3D 0bject textSize(30); fill(0, 76, 153); box (386, 40, 200); // Draw box textSize(25); fill(255, 255, 255); text("www.HowToMechatronics.com", -183, 10, 101); //delay(10); //println("ypr:\t" + angleX + "\t" + angleY); // Print the values to check whether we are getting proper values } // Read data from the Serial Port void serialEvent (Serial myPort) { // reads the data from the Serial Port up to the character '.' and puts it into the String variable "data". data = myPort.readStringUntil('\n'); // if you got any bytes other than the linefeed: if (data != null) { data = trim(data); // split the string at "/" String items[] = split(data, '/'); if (items.length > 1) { //--- Roll,Pitch in degrees roll = float(items[0]); pitch = float(items[1]); } } }Code language: Arduino (arduino)
Deskripsi: Jadi di sini, kita perlu menyertakan library serial, mendefinisikan port serial dan baud rate yang harus sesuai dengan baud rate sketsa Arduino yang diunggah. Kemudian kita membaca data masuk dan memasukkannya ke dalam variabel roll dan pitch yang sesuai. Dalam loop draw utama, kita menggunakan nilai-nilai ini untuk memutar objek 3D, dan dalam hal ini itu adalah kotak sederhana yang memiliki warna tertentu dan teks di atasnya.
Jika kita menjalankan sketsa ini, objek 3D akan muncul dan akan melacak orientasi sensor akselerometer. Kita dapat memperhatikan di sini bahwa objek sedikit goyah dan itu karena akselerometer menangkap tidak hanya gaya gravitasi, tetapi juga gaya kecil yang dihasilkan oleh gerakan tangan kita. Untuk mendapatkan hasil yang lebih halus, kita dapat menggunakan filter Low-pass sederhana. Di sini saya mengimplementasikan filter tersebut dalam kode Arduino, yang mengambil 94% dari keadaan sebelumnya dan menambahkan 6% dari keadaan atau sudut saat ini.
Dengan filter ini, kita dapat memperhatikan bahwa objek bergerak jauh lebih halus sekarang, tetapi ada juga efek samping dan itu adalah responsivitas yang lebih lambat. Kita juga dapat memperhatikan bahwa Yaw hilang, atau rotasi di sekitar sumbu Z. Menggunakan hanya data akselerometer 3-sumbu kita tidak dapat menghitung Yaw.
Untuk melakukannya dan meningkatkan kinerja keseluruhan sensor pelacakan orientasi kami, kita sebenarnya perlu menyertakan sensor tambahan, giro, dan menggabungkan datanya dengan akselerometer.
Jadi, kita dapat menggunakan akselerometer ADXL345 dalam kombinasi dengan sensor giro, atau menggunakan IMU MPU6050 yang memiliki akselerometer 3-sumbu dan giro 3-sumbu yang terintegrasi pada satu chip. Anda dapat menemukan tutorial yang lebih rinci tentang sensor ini dalam video berikutnya saya.
Saya harap Anda menikmati tutorial ini dan mempelajari hal baru. Jangan ragu untuk bertanya apa pun di bagian komentar di bawah dan jangan lupa untuk memeriksa koleksi Proyek Arduino saya.