Apa itu MEMS? Akselerometer, Giroskop &Magnetometer dengan Arduino
Dalam tutorial ini, kita akan mempelajari cara kerja akselerometer, giroskop, dan magnetometer MEMS serta cara menggunakannya dengan Papan Arduino. Juga dengan Processing IDE kami akan membuat beberapa aplikasi praktis menggunakan sensor. Anda dapat menonton video berikut atau membaca tutorial tertulis di bawah ini.
Apa itu MEMS?
MEMS adalah sistem atau perangkat yang sangat kecil, terdiri dari komponen mikro berukuran mulai dari 0,001 mm hingga 0,1 mm. Komponen ini terbuat dari silikon, polimer, logam dan/atau keramik, dan biasanya digabungkan dengan CPU (Mikrokontroler) untuk melengkapi sistem.
Sekarang kami akan menjelaskan secara singkat cara kerja masing-masing sensor Micro-Electro-Mechanical-Systems (MEMS) ini.
Akselerometer MEMS
Ini mengukur percepatan dengan mengukur perubahan kapasitansi. Struktur mikronya terlihat seperti ini. Ini memiliki massa yang melekat pada pegas yang terbatas untuk bergerak sepanjang satu arah dan pelat luar tetap. Jadi ketika percepatan dalam arah tertentu akan diterapkan, massa akan bergerak dan kapasitansi antara pelat dan massa akan berubah. Perubahan kapasitansi ini akan diukur, diproses dan akan sesuai dengan nilai percepatan tertentu.
Giroskop MEMS
Giroskop mengukur laju sudut menggunakan Efek Coriolis. Ketika sebuah massa bergerak dalam arah tertentu dengan kecepatan tertentu dan ketika laju sudut eksternal akan diterapkan seperti yang ditunjukkan dengan panah hijau, sebuah gaya akan terjadi, seperti yang ditunjukkan dengan panah merah biru, yang akan menyebabkan perpindahan tegak lurus dari massa. Begitu mirip dengan accelerometer, perpindahan ini akan menyebabkan perubahan kapasitansi yang akan diukur, diproses dan akan sesuai dengan kecepatan sudut tertentu.
Struktur mikro giroskop terlihat seperti ini. Sebuah massa yang terus bergerak, atau berosilasi, dan ketika laju sudut eksternal akan diterapkan, bagian fleksibel dari massa akan bergerak dan membuat perpindahan tegak lurus.
Magnetometer MEMS
Ini mengukur medan magnet bumi dengan menggunakan Hall Effect atau Magneto Resistive Effect. Sebenarnya hampir 90% sensor di pasaran menggunakan Efek Hall dan begini cara kerjanya.
Jika kita memiliki pelat konduktif seperti yang ditunjukkan pada foto dan kita mengatur arus untuk mengalir melaluinya, elektron akan mengalir langsung dari satu sisi ke sisi pelat lainnya. Sekarang jika kita membawa beberapa medan magnet di dekat pelat, kita akan mengganggu aliran lurus dan elektron akan membelok ke satu sisi pelat dan kutub positif ke sisi lain pelat. Artinya jika kita menempatkan meter sekarang di antara kedua sisi ini kita akan mendapatkan tegangan yang tergantung dari kekuatan medan magnet dan arahnya.
10% sensor lainnya di pasaran menggunakan Efek Magneto-resistive. Sensor ini menggunakan bahan yang peka terhadap medan magnet, biasanya terdiri dari Besi (Fe) dan Nikel (Ne). Jadi ketika bahan-bahan ini terkena medan magnet, mereka mengubah resistansinya.
Sensor Arduino dan MEMs
Ok sekarang mari kita sambungkan sensor-sensor ini ke Papan Arduino dan menggunakannya. Sebagai contoh saya akan menggunakan papan breakout GY-80 yang memiliki sensor berikut:ADXL345 3 Axis Accelerometer, L3G4200D 3 Axis Gyroscope, MC5883L 3 Axis Magnetometer dan juga Barometer dan Termometer yang tidak akan kita gunakan dalam tutorial ini.
Anda bisa mendapatkan komponen ini dari salah satu situs di bawah:
ADXL345 3-Sumbu Akselerator………………………………………………………
2 in 1:Giroskop &Akselerometer 6 Sumbu MPU6050 …………………
3 in 1:GY-80 9-Axis Magnetic Field Acceleration Giroskop……… Amazon
Board ini menggunakan protokol komunikasi I2C yang berarti kita dapat menggunakan semua sensor hanya dengan dua kabel. Jadi untuk membuat komunikasi antara Arduino dan sensor, kita perlu mengetahui alamat perangkat unik mereka dan alamat register internal mereka untuk mendapatkan data dari mereka. Alamat ini dapat ditemukan dari lembar data sensor:
ADXL345 Akselerometer Lembar Data
L3G4200D Giroskop Lembar data
MC5883L Magnetometer Lembar data
Untuk detail selengkapnya tentang cara kerja komunikasi I2C, Anda dapat melihat Tutorial Protokol Komunikasi I2C saya yang lain.
Kode Sumber
Sekarang mari kita lihat kode untuk mendapatkan data dari sensor. Kita akan mulai dengan akselerometer dan akan ada beberapa penjelasan sebelum setiap kode, serta beberapa deskripsi tambahan di komentar kode.
Kode Akselerometer Arduino
Pertama kita perlu menyertakan Perpustakaan Kawat Arduino dan menentukan alamat register sensor. Di bagian setup kita perlu memulai Wire Library dan memulai komunikasi serial karena kita akan menggunakan monitor serial untuk menampilkan hasilnya. Juga di sini kita perlu mengaktifkan sensor, atau mengaktifkan pengukuran dengan mengirimkan byte yang sesuai ke register Power_CTL dan inilah cara kita melakukannya. Menggunakan fungsi Wire.beginTransmission() kita memilih sensor mana yang akan kita bicarakan, Akselerometer 3-Sumbu dalam hal ini. Kemudian menggunakan fungsi Wire.write() kita memberitahu register internal mana yang akan kita bicarakan. Setelah ini kami akan mengirimkan byte yang sesuai untuk mengaktifkan pengukuran. Menggunakan fungsi Wire.endTransmission() kita akan mengakhiri transmisi dan itu akan mengirimkan data ke register.
Di bagian loop kita perlu membaca data untuk setiap sumbu. Kita akan mulai dengan X – Sumbu. Jadi pertama-tama kita akan memilih register mana yang akan kita bicarakan, dua register internal X – Axis dalam hal ini. Kemudian menggunakan fungsi Wire.requestFrom() kami akan meminta data yang dikirimkan atau dua byte dari dua register. Wire.available() fungsi akan mengembalikan jumlah byte yang tersedia untuk pengambilan dan jika jumlah tersebut cocok dengan byte yang kami minta, dalam kasus kami 2 byte, menggunakan Wire.read() fungsi kita akan membaca byte dari dua register sumbu X.
Data keluaran dari register adalah komplemen dua, dengan X0 sebagai byte paling signifikan dan X1 sebagai byte paling signifikan sehingga kita perlu mengubah byte ini menjadi nilai float dari -1 hingga +1 bergantung pada arah relatif X – Sumbu terhadap percepatan bumi atau gravitasi. Kami akan mengulangi prosedur ini untuk dua sumbu lainnya dan pada akhirnya kami akan mencetak nilai-nilai ini pada monitor serial.
#include <Wire.h>
//--- Accelerometer Register Addresses
#define Power_Register 0x2D
#define X_Axis_Register_DATAX0 0x32 // Hexadecima address for the DATAX0 internal register.
#define X_Axis_Register_DATAX1 0x33 // Hexadecima address for the DATAX1 internal register.
#define Y_Axis_Register_DATAY0 0x34
#define Y_Axis_Register_DATAY1 0x35
#define Z_Axis_Register_DATAZ0 0x36
#define Z_Axis_Register_DATAZ1 0x37
int ADXAddress = 0x53; //Device address in which is also included the 8th bit for selecting the mode, read in this case.
int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
float Xa,Ya,Za;
void setup() {
Wire.begin(); // Initiate the Wire library
Serial.begin(9600);
delay(100);
Wire.beginTransmission(ADXAddress);
Wire.write(Power_Register); // Power_CTL Register
// Enable measurement
Wire.write(8); // Bit D3 High for measuring enable (0000 1000)
Wire.endTransmission();
}
void loop() {
// X-axis
Wire.beginTransmission(ADXAddress); // Begin transmission to the Sensor
//Ask the particular registers for data
Wire.write(X_Axis_Register_DATAX0);
Wire.write(X_Axis_Register_DATAX1);
Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers
Wire.requestFrom(ADXAddress,2); // Request the transmitted two bytes from the two registers
if(Wire.available()<=2) { //
X0 = Wire.read(); // Reads the data from the register
X1 = Wire.read();
/* Converting the raw data of the X-Axis into X-Axis Acceleration
- The output data is Two's complement
- X0 as the least significant byte
- X1 as the most significant byte */
X1=X1<<8;
X_out =X0+X1;
Xa=X_out/256.0; // Xa = output value from -1 to +1, Gravity acceleration acting on the X-Axis
}
// Y-Axis
Wire.beginTransmission(ADXAddress);
Wire.write(Y_Axis_Register_DATAY0);
Wire.write(Y_Axis_Register_DATAY1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2) {
Y0 = Wire.read();
Y1 = Wire.read();
Y1=Y1<<8;
Y_out =Y0+Y1;
Ya=Y_out/256.0;
}
// Z-Axis
Wire.beginTransmission(ADXAddress);
Wire.write(Z_Axis_Register_DATAZ0);
Wire.write(Z_Axis_Register_DATAZ1);
Wire.endTransmission();
Wire.requestFrom(ADXAddress,2);
if(Wire.available()<=2) {
Z0 = Wire.read();
Z1 = Wire.read();
Z1=Z1<<8;
Z_out =Z0+Z1;
Za=Z_out/256.0;
}
// Prints the data on the Serial Monitor
Serial.print("Xa= ");
Serial.print(Xa);
Serial.print(" Ya= ");
Serial.print(Ya);
Serial.print(" Za= ");
Serial.println(Za);
}
Code language: Arduino (arduino)
Kode Giroskop Arduino
Untuk mendapatkan data dari giroskop kita akan memiliki kode yang sama seperti yang sebelumnya. Jadi pertama-tama kita harus mendefinisikan alamat register dan beberapa variabel untuk data. Di bagian setup kita harus bangun dan menempatkan sensor dalam mode normal menggunakan CTRL_REG1 dan juga memilih sensitivitas sensor. Untuk contoh ini saya akan memilih mode sensitivitas 2000dps.
Pada bagian loop yang mirip dengan accelerometer kita akan membaca data untuk sumbu X, Y dan Z. Kemudian data mentah harus diubah menjadi nilai sudut. Dari lembar data sensor kita dapat melihat bahwa untuk mode sensitivitas 2000dps sesuai dengan unit 70 mdps/digit. Ini berarti bahwa kita harus mengalikan data keluaran mentah dengan 0,07 untuk mendapatkan laju sudut dalam derajat per detik. Kemudian jika mengalikan laju sudut dengan waktu, itu akan memberi kita nilai sudut. Jadi kita perlu menghitung interval waktu setiap bagian loop dan kita bisa melakukannya dengan menggunakan fungsi millis() di bagian atas dan bawah bagian loop, dan kita akan menyimpan nilainya ke dalam variabel “dt” ini. Jadi untuk setiap loop yang dieksekusi, kami akan menghitung sudut dan menambahkannya ke nilai sudut akhir. Kami akan melakukan hal yang sama untuk dua sumbu lainnya dan pada akhirnya kami akan mencetak hasilnya di monitor serial.
#include <Wire.h>
//--- Gyro Register Addresses
#define Gyro_gX0 0x28
#define Gyro_gX1 0x29
#define Gyro_gY0 0x2A
#define Gyro_gY1 0x2B
#define Gyro_gZ0 0x2C
#define Gyro_gZ1 0x2D
int Gyro = 0x69; //Device address in which is also included the 8th bit for selecting the mode, read in this case.
int gX0, gX1, gX_out;
int gY0, gY1, gY_out;
int gZ0, gZ1, gZ_out;
float Xg,Yg,Zg;
float angleX,angleY,angleZ,angleXc,angleYc,angleZc;
unsigned long start, finished, elapsed;
float dt=0.015;
void setup()
{
Wire.begin();
Serial.begin(9600);
delay(100);
Wire.beginTransmission(Gyro);
Wire.write(0x20); // CTRL_REG1 - Power Mode
Wire.write(15); // Normal mode: 15d - 00001111b
Wire.endTransmission();
Wire.beginTransmission(Gyro);
Wire.write(0x23); // CTRL_REG4 - Sensitivity, Scale Selection
Wire.write(48); // 2000dps: 48d - 00110000b
Wire.endTransmission();
}
void loop()
{
start=millis();
//---- X-Axis
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gX0);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gX0 = Wire.read();
}
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gX1);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gX1 = Wire.read();
}
//---- Y-Axis
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gY0);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gY0 = Wire.read();
}
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gY1);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gY1 = Wire.read();
}
//---- Z-Axis
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gZ0);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gZ0 = Wire.read();
}
Wire.beginTransmission(Gyro); // transmit to device
Wire.write(Gyro_gZ1);
Wire.endTransmission();
Wire.requestFrom(Gyro,1);
if(Wire.available()<=1)
{
gZ1 = Wire.read();
}
//---------- X - Axis
// Raw Data
gX1=gX1<<8;
gX_out =gX0+gX1;
// From the datasheet: 70 mdps/digit
Xg=gX_out*0.07; // Angular rate
// Angular_rate * dt = angle
angleXc = Xg*dt;
angleX = angleX + angleXc;
//---------- Y - Axis
gY1=gY1<<8;
gY_out =gY0+gY1;
Yg=gY_out*0.07;
angleYc = Yg*dt;
angleY = angleY + angleYc;
//---------- Z - Axis
gZ1=gZ1<<8;
gZ_out =gZ0+gZ1;
Zg=gZ_out*0.07;
angleZc = Zg*dt;
angleZ = angleZ + angleZc;
// Prints the data on the Serial Monitor
Serial.print("angleX= ");
Serial.print(angleX);
Serial.print(" angleY= ");
Serial.print(angleY);
Serial.print(" angleZ= ");
Serial.println(angleZ);
delay(10);
// Calculating dt
finished=millis();
elapsed=finished-start;
dt=elapsed/1000.0;
start = elapsed = 0;
}Code language: Arduino (arduino)
Kode Magnetometer Arduino
Sekali lagi kita akan menggunakan teknik yang mirip dengan yang sebelumnya. Pertama kita perlu mendefinisikan alamat register dan bagian setup mengatur sensor dalam mode pengukuran kontinu. Di bagian loop kita akan mendapatkan data mentah untuk setiap sumbu dengan metode yang sama seperti untuk sensor sebelumnya.
Kemudian, kita perlu mengubah data mentah menjadi nilai medan magnet atau satuan Gauss. Dari datasheet sensor kita dapat melihat bahwa mode sensitivitas default adalah 0,92mG/digit. Itu berarti kita perlu mengalikan data mentah dengan 0,00092 untuk mendapatkan medan magnet bumi dalam satuan Gauss. Pada akhirnya kami akan mencetak nilai pada monitor serial.
#include <Wire.h> //I2C Arduino Library
#define Magnetometer_mX0 0x03
#define Magnetometer_mX1 0x04
#define Magnetometer_mZ0 0x05
#define Magnetometer_mZ1 0x06
#define Magnetometer_mY0 0x07
#define Magnetometer_mY1 0x08
int mX0, mX1, mX_out;
int mY0, mY1, mY_out;
int mZ0, mZ1, mZ_out;
float Xm,Ym,Zm;
#define Magnetometer 0x1E //I2C 7bit address of HMC5883
void setup(){
//Initialize Serial and I2C communications
Serial.begin(9600);
Wire.begin();
delay(100);
Wire.beginTransmission(Magnetometer);
Wire.write(0x02); // Select mode register
Wire.write(0x00); // Continuous measurement mode
Wire.endTransmission();
}
void loop(){
//---- X-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mX0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mX1 = Wire.read();
}
//---- Y-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mY0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mY1 = Wire.read();
}
//---- Z-Axis
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ1);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ0 = Wire.read();
}
Wire.beginTransmission(Magnetometer); // transmit to device
Wire.write(Magnetometer_mZ0);
Wire.endTransmission();
Wire.requestFrom(Magnetometer,1);
if(Wire.available()<=1)
{
mZ1 = Wire.read();
}
//---- X-Axis
mX1=mX1<<8;
mX_out =mX0+mX1; // Raw data
// From the datasheet: 0.92 mG/digit
Xm = mX_out*0.00092; // Gauss unit
//* Earth magnetic field ranges from 0.25 to 0.65 Gauss, so these are the values that we need to get approximately.
//---- Y-Axis
mY1=mY1<<8;
mY_out =mY0+mY1;
Ym = mY_out*0.00092;
//---- Z-Axis
mZ1=mZ1<<8;
mZ_out =mZ0+mZ1;
Zm = mZ_out*0.00092;
//Print out values of each axis
Serial.print("x: ");
Serial.print(Xm);
Serial.print(" y: ");
Serial.print(Ym);
Serial.print(" z: ");
Serial.println(Zm);
delay(50);
}Code language: Arduino (arduino)
Berikut adalah aplikasi sensor yang tampak keren, kompas digital MEMS, yang dibuat menggunakan Processing IDE. Anda dapat menemukan detail selengkapnya dan kode sumber dari contoh ini pada link berikut: