Membuat Kompas Digital Real-Time dengan Arduino & Processing
Dalam Proyek Arduino ini kita akan melihat bagaimana kita dapat membuat kompas yang tampak keren ini menggunakan Arduino, Sensor Magnetometer MEMS dan IDE Processing. Berikut adalah video demonstrasi kompas:
Ringkasan
Yang kita butuhkan untuk proyek ini adalah Sensor Magnetometer MEMS, untuk mengukur medan magnet bumi, Papan Arduino dan beberapa kabel jumper. Sebagai contoh saya akan menggunakan HMC5883L, Magnetometer 3 – Sumbu yang terintegrasi pada papan breakout GY–80.
Bagaimana Kompas Bekerja
Bagian Arduino
Pertama kita perlu mendapatkan data dari sensor menggunakan Papan Arduino melalui protokol I2C. Kemudian menggunakan nilai X – Axis dan Y – Axis dari sensor kita akan menghitung heading dan mengirim nilainya ke IDE Processing melalui Port Serial. Kode berikut akan melakukan pekerjaan tersebut:
/* Arduino Compass * * by Dejan Nedelkovski, * www.HowToMechatronics.com * */ #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 heading, headingDegrees, headingFiltered, declination; float Xm,Ym,Zm; #define Magnetometer 0x1E //I2C 7bit address of HMC5883 void setup(){ //Initialize Serial and I2C communications Serial.begin(115200); 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; // ============================== //Calculating Heading heading = atan2(Ym, Xm); // Correcting the heading with the declination angle depending on your location // You can find your declination angle at: https://www.ngdc.noaa.gov/geomag-web/ // At my location it's 4.2 degrees => 0.073 rad declination = 0.073; heading += declination; // Correcting when signs are reveresed if(heading <0) heading += 2*PI; // Correcting due to the addition of the declination angle if(heading > 2*PI)heading -= 2*PI; headingDegrees = heading * 180/PI; // The heading in Degrees unit // Smoothing the output angle / Low pass filter headingFiltered = headingFiltered*0.85 + headingDegrees*0.15; //Sending the heading value through the Serial Port to Processing IDE Serial.println(headingFiltered); delay(50); }Code language: Arduino (arduino)
Jika Anda membutuhkan detail lebih lanjut tentang cara kerja Sensor Magnetometer MEMS dan cara mendapatkan datanya, Anda dapat memeriksa Tutorial Sensor MEMS saya.
Bagian IDE Processing
Di sini pertama-tama kita perlu menerima nilai heading yang datang dari Port Serial. Untuk detail lebih lanjut bagaimana ini dilakukan Anda dapat memeriksa Tutorial Arduino dan Processing saya.
Kompas sebenarnya adalah gambar, atau lebih tepatnya, terdiri dari beberapa gambar transparan yang dimuat ke dalam IDE Processing. Gambar-gambar harus terletak di direktori kerja sketsa. Setelah mendefinisikan objek gambar di bagian draw() menggunakan fungsi image() kita memuat gambar latar belakang (yang bersifat opsional, Anda dapat menggunakan warna sederhana untuk latar belakang). Kemudian gambar Kompas dimuat yang menggunakan fungsi rotateZ() diputar dengan nilai heading. Di atasnya gambar Panah Kompas dimuat.
Berikut adalah Kode IDE Processing:
/* Arduino Compass * * by Dejan Nedelkovski, * www.HowToMechatronics.com * */ import processing.serial.*; import java.awt.event.KeyEvent; import java.io.IOException; Serial myPort; PImage imgCompass; PImage imgCompassArrow; PImage background; String data=""; float heading; void setup() { size (1920, 1080, P3D); smooth(); imgCompass = loadImage("Compass.png"); imgCompassArrow = loadImage("CompassArrow.png"); background = loadImage("Background.png"); myPort = new Serial(this, "COM4", 115200); // starts the serial communication myPort.bufferUntil('\n'); } void draw() { image(background,0, 0); // Loads the Background image pushMatrix(); translate(width/2, height/2, 0); // Translates the coordinate system into the center of the screen, so that the rotation happen right in the center rotateZ(radians(-heading)); // Rotates the Compass around Z - Axis image(imgCompass, -960, -540); // Loads the Compass image and as the coordinate system is relocated we need need to set the image at -960x, -540y (half the screen size) popMatrix(); // Brings coordinate system is back to the original position 0,0,0 image(imgCompassArrow,0, 0); // Loads the CompassArrow image which is not affected by the rotateZ() function because of the popMatrix() function textSize(30); text("Heading: " + heading,40,40); // Prints the value of the heading on the screen delay(40); } // starts reading data from the Serial Port void serialEvent (Serial myPort) { data = myPort.readStringUntil('\n');// reads the data from the Serial Port and puts it into the String variable "data". heading = float(data); // Convering the the String value into Float value } Code language: Arduino (arduino)
Di sini Anda dapat mengunduh file dari proyek, gambar dan kode sumber: