В этом проекте мы рассмотрим как можно сделать этот круто выглядящий компас, используя плату Arduino, магнитометр MEMS и Processing IDE. Визуально компас будет отображать данные на экране вашего компьютера, но если вы хотите изготовить компас в «готовом» виде, то советуем посмотреть этот проект цифрового компаса на основе Arduino и магнитометра HMC5883L.
Все, что нам нужно для этого проекта, — это MEMS магнитометр для измерения магнитного поля Земли, плата Arduino и соединительные провода. В качестве примера мы будем использовать HMC5883L, 3-осевой магнитометр, встроенный в коммутационную плату GY-80, работу с которым мы рассматривали в этой статье про подключение датчиков MEMS к плате Arduino. Но также можно использовать и отдельный модуль магнитометра HMC5883L (купить на AliExpress).
Как работает компас
Часть Ардуино
Сначала нам нужно получить данные от датчика с помощью платы Arduino по протоколу I2C. Затем, используя значения оси X и оси Y датчика, мы рассчитаем курс и отправим его значение в Processing IDE через последовательный порт. Следующий код выполнит эту работу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
/* 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); } |
Часть Processing IDE
‘Processing’ представляет собой программное обеспечение с открытым исходным кодом, которое часто используется энтузиастами в графическом дизайне. На нашем сайте мы уже рассматривали достаточно много проектов с использованием Processing IDE, которые можно посмотреть по следующей ссылке, наиболее популярными из них являются:
- радар с использованием Arduino, ультразвукового датчика и приложения на Android;
- спидометр с использованием Arduino и приложения на Android;
- плоттер с ЧПУ на основе Arduino Uno;
- измеритель уровня (уклономер) на основе Arduino и MPU6050.
Также вы можете прочитать отдельное подробное руководство про взаимодействие Arduino и Processing, которое поможет вам лучше понять этот проект цифрового компаса.
В этом проекте нам сначала нужно получить значения заголовков, поступающие из последовательного порта.
Компас на самом деле представляет собой изображение, точнее, он состоит из нескольких прозрачных изображений, загруженных в Processing IDE. Изображения должны располагаться в рабочей папке эскиза. После определения объектов изображений в разделе draw() с помощью функции image() мы загружаем фоновое изображение (это необязательно, вы можете использовать простой цвет для фона). Затем загружается изображение компаса, которое с помощью функции RotateZ() поворачивается в соответствии со значениями заголовка. Поверх них загружается изображение стрелки компаса.
Вот код Processing IDE:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
/* 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 } |
Также все файлы, необходимые для данного проекта, вы можете скачать по следующей ссылке.
2 ответа к “Как сделать компас с помощью Arduino и Processing IDE”
Интересно, спасибо.
Спасибо, стараемся.