在这个Arduino项目中,我们将看到我们如何使用Arduino,MEMS磁力计和处理IDE来使这块酷炫的指南针。这是指南针的示范视频:
概述
我们所需的所有项目都是MEMS磁力计,用于测量地球磁场,Arduino板和一些跳线。作为一个例子,我将使用HMC5883L,一台3轴磁力计集成在GY-80 Breakout板中。
指南针如何工作
Arduino部分
首先我们需要通过Arduino板从传感器获取数据I2C协议。然后使用传感器的X轴和Y轴值,我们将通过串行端口计算标题并将其值发送到处理IDE。以下代码将执行此作业:
/ * Arduino罗盘由德扬Nedelkovski * *, * www.HowToMechatr亚搏手机版官方下载onics.com * * / # include < Wire.h > / / I2C Arduino图书馆# define Magnetometer_mX0 0 x03 # define Magnetometer_mX1 x04 #定义Magnetometer_mZ0 0 x05 # define Magnetometer_mZ1 x06 #定义Magnetometer_mY0 0 x07 # define Magnetometer_mY1 (int mX0, mx₁,mX_out;int mY0, mY1, mY_out;int mZ0, mZ1, mZ_out;浮动航向,航向度,航向过滤,赤纬;Zm评选浮动Xm, Ym;void setup(){//初始化串行和I2C通信串行.begin(115200);Wire.begin ();延迟(100);Wire.beginTransmission(磁强计);Wire.write (0 x02); // 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); }
如果你需要更多的细节如何MEMS磁强计的工作和如何从它获得数据,你可以检查我的MEMS传感器教程。
处理IDE部分
在这里,我们需要接收来自串行端口的标题值。有关更多详细信息,您可以查看此操作Arduino和处理教程。
指南针实际上是一幅图像,或者更准确地说,它是由加载到处理IDE中的多个透明图像组成的。这些图像位于草图的工作目录中。在使用image()函数在draw()部分定义了图像对象之后,我们加载了背景图像(这是可选的,您可以使用一个简单的颜色作为背景)。然后,使用rotateZ()函数加载罗盘图像,并将其与标题值一起旋转。在它们的顶部,罗盘箭头图像被加载。
这是处理IDE代码:
/ * Arduino Compass * * by dejan nedelkovski,* www.亚搏手机版官方下载www.kuaixg.com * * /导入处理。*;导入java.awt.Event.keyEvent;导入java.io.ioException;串行MyPort;pimage imgcompass;pimage imgcompassarrow;瞄准器背景;字符串数据=“”;浮动标题;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 }
在这里,您可以从项目,图像和源代码下载文件:
这段代码将在Teensy3,Arduino Zero,Arduino到期,Chipkit,ESP8266和所有其他新型32位板上失败。
问题与符号整数的两个8位无符号号码不正确。数学实际上计算了0到65535的数字,因为Wire.read()的数字为0到255.在8位AVR上,存储到16位“int”时,不正确的计算变为-32768至+32767。但在32位芯片上,计算会导致无符号0到65536,因为“int”是32位。
“int”变量需要更改为“int16_t”以在任何32个位板上进行此操作。
谢谢,这是一个很好的评论!
嗨德国,非常感谢您所有的伟大项目。足彩网女欧洲杯
我尝试了这个,但我在第29行得到了一个空指针例外。
你知道怎么了吗?
什么是第29行?处理IDE代码可能会出于某种原因堆叠的东西,并且需要将Arduino重新插入USB端口。
嗨Dejan,
对不起,我不清楚。处理草图在第29行失败;有这个“null指针例外”。我试图重新计算Arduino,但仍然是错误。
这是令人惊讶的,因为您的mems传感器代码在我的系统上都工作得很好,您的雷达项目也工作得很好。
对不起,我刚看过失败的细节。缺少文件compass.png,compassarrow.png和background arruction arrow.png。我怎么能得到它们?
嗨Dejan,我应该在你的页面上更仔细看,发现图片文件,并包含一旦包含系统工作。
多谢!!
很高兴听到它的作用!
美丽的设计,但......
如何在TFT LCD屏幕3.2上使用它,例如,而不是计算机屏幕?谢谢
谢谢。好吧,检查我的Arduino TFT触摸屏教程。
嗨朋友!伟大的设计!
我想在TFT LCD屏幕上这样做3.2“是可能的吗?
谢谢
嗨,伟大的网站。
请您详细解释一下如何将传感器输出转换成角度和方向。
我正在寻找传感器的角度和方向,我将传感器移动到已知距离。
我实际上希望将数据存储或在数据记录器中存储或看到,如角度和方向。
如果问题如此简单和愚蠢,我对arduino很抱歉。
谢谢
这能补偿倾斜吗?
不,倾斜补偿在这段代码中没有实现。