风筝
发表于: 2018-11-27 23:15:16 | 显示全部楼层

人类大脑由复杂的结构层构成,这让我们成为地球上的优势物种。例如,大脑中的内嗅皮层可以让您感觉方向,帮助您轻松导航您不熟悉的地方。但与我们不同的是,机器人和无人驾驶飞行器UAV需要一些辅助设备才能获得这种方向感,这样他们就可以在新的地形和风景中自主操纵。不同的机器人使用不同类型的传感器来实现这一点,但常用的是磁力计,它可以通知机器人当前面向的地理方向。这不仅有助于机器人感知方向,还可以以预定义的方向和角度中转弯。

Digital-Compass-using-Arduino-and-HMC5883L-Magnetometer.jpg


由于传感器可以指示地理位置上的南、北、东和西,我们人类也可以在需要时使用它。因此,在本篇文章中,让我们尝试了解磁力计传感器的工作原理以及如何将其连接到Arduino开发板等微控制器。在文章中,我们将制作一个很酷的数字罗盘,它可以点亮指向北方向的LED灯来帮助我们辨别出方向。这款数字罗盘的PCB是在PCBGOGO网站制作,这样下次我出去的时候就可以随身携带它,并希望在我迷路的时候,可以使用它找到回家的路。让我们开始吧。


所需的组件

●    Arduino Pro mini开发板

●    HMC5883L磁力计传感器

●    8个LED指示灯

●    470欧姆电阻

●    FTDI Programmer烧写器

●    PC /笔记本电脑


什么是磁力计?它是如何工作的?

在深入研究电路之前,让我们先了解一下磁力计及其工作原理。顾名思义,Magneto这个词并不是指那个可以通过弹奏钢琴来控制金属疯狂的万磁王。不过,我很喜欢那个很酷的家伙。


磁力计实际上是一种能够感应地球磁极并根据其指向方向的设备。我们都知道地球是一块巨大的球形磁铁,有北极和南极。因此有磁场。磁力计可以感应到这个磁场,并且根据磁场的方向,它可以检测到我们所面对的方向。


HMC5883L传感器模块的工作原理

作为磁力计传感器的HMC5883L也是同样原理。该传感器模块使用的是霍尼韦尔的HMC5883L。该IC内部有3个磁阻材料,放置在轴x、y和z中。流过这些材料的电流量对地球的磁场敏感。因此,通过测量流过这些材料的电流变化,我们可以检测到地球磁场的变化。一旦磁场发生变化,就可以通过I2C协议将值发送到任何嵌入式控制器,如微控制器或处理器。


由于传感器通过感应磁场工作,如果在附近放置金属,输出值将受到很大影响。可以利用这种现象将这些传感器用作金属探测器。应注意不要在此传感器附近放置磁铁,因为磁铁的强磁场可能会触发传感器上的错误值。


HMC5883L和QMC5883L之间的区别

对于许多初学者来说,这些传感器很容易令人混淆。这是因为一些供应商(实际上是大多数)销售的是QMC5883L传感器而不是霍尼韦尔的原装HMC5883L。这主要是因为QMC5883L比HMC5883L模块便宜。可悲的是,这两个传感器的工作略有不同,两者都不能使用相同的代码。这是因为两个传感器的I2C地址不一样。本教程中的代码仅适用于常用的传感器模块QMC5883L。


QMC5883L-Magnetometer-sensor.jpg


要想知道您所拥有的传感器型号,您只需要仔细查看IC本身,读取其上面的内容。如果它写的是类似L883那么它就是HMC58836L,如果写的是像DA5883那么它就是QMC5883L IC。两个模块如下图所示。

Difference-between-HMC5883L-and-QMC5883L.png


电路原理图

这款基于Arduino的数字罗盘的电路非常简单,我们只需要将HMC5883L传感器与Arduino连接,并将8个LED连接到Arduino Pro mini的GPIO引脚。完整的电路图如下所示

Circuit-Diagram-for-Digital-Compass-using-Arduino-and-HMC5883L-Magnetometer.png

传感器模块有5个引脚,因为我们在连续模式下操作传感器,因此我们的项目中没有使用DRDY(数据就绪)。 Vcc和接地引脚通过Arduino板上的5V为模块供电。 SCL和SDA是I2C通信总线,分别连接到Arduino Pro mini的I2C引脚A4和A5。由于模块本身在线路上有一个上拉电阻,因此无需在外部添加它们。


为了指示方向,我们使用了8个LED灯,所有这些LED都通过470欧姆的限流电阻连接到Arduino的GPIO引脚。完整电路由9V电池供电。该9V直接提供给Arduino的Vin引脚,使用Arduino上的板载稳压器将其调节至5V。然后,该5V用于为传感器和Arduino供电。


制造数字罗盘的PCB

该电路的想法是将8个LED以圆形方式放置,使得每个Led分别指向所有8个方向,即分别为北、东北、东、东南、南、西南、西和西北。因此,将它们整齐地安排在面包板上并不容易。为此电路开发PCB将使其看起来更整洁,易于使用。所以我使用PCB设计软​​件,将LED和电阻器放在一个整齐的圆形图案中,并连接了导线连接在一起。完成后,我的PCB设计看起来如下所示。您也可以从给定的链接下载Gerber文件。

Fabricating-the-PCBs-for-the-Digital-Compass.png

我将它设计成双面板,因为我希望Arduino位于PCB的底部,这样它就不会破坏PCB顶部的外观。


现在,我们的设计准备就绪,是时候让它们制作完成了。要完成PCB操作非常简单,只需按照以下步骤操作即可

第1步:进入www.pcbgogo.com,如果这是您第一次访问,请先注册账号。然后,在PCB Prototype选项卡中输入PCB的尺寸、层数和所需的PCB数量。我的PCB是80厘米×80厘米,所以选项卡如下所示

Enter-PCB-dimensions-on-PCBgogo-Website.png

第2步:单击“立即报价”按钮继续。如果需要,您将进入一个页面,在那里设置一些额外的参数,如使用的材料、导线间距等。但大多数默认值都可以。我们在这里唯一需要考虑的是价格和时间。正如您所看到的,制作时间仅为2-3天,我们的PSB仅需5美元。然后,您可以根据您的要求选择首选送货方式。

Order-PCB-for-DIgital-Compass-from-PCBgogo.png


第3步:最后一步是上传Gerber文件并继续付款。为了确保流程顺利,PCBGOGO会在继续付款之前验证您的Gerber文件是否有效。通过这种方式,您可以确保您的PCB具有制造友好性,并可以按照承诺与您联系。


PCB电路板装配

在订购了这块板之后,几天后就收到一个整齐标记好的包装盒中的快递,并且像PCB的质量令人敬畏。我分享下面几块电路板的图片。

PCB-for-Digital-Compass-using-Arduino-and-HMC5883L-Magnetometer.jpg


然后我开始组装电路板。由于封装、焊盘、过孔和丝网印刷的形状和尺寸都非常合适,因此组装电路板时没有任何问题。仅仅用了十几分钟,电路板就焊接好了。

焊接后电路板的图片如下所示。

Soldered-Components-on-PCB-for-Digital-Compass.jpg

跳转到指定楼层
风筝
发表于: 2018-11-28 19:52:16 | 显示全部楼层

编程Arduino开发板

现在硬件已准备就绪,让我们看一下上传到Arduino开发板的程序。该代码主要是从QMC5883L磁力计传感器读取数据并将其转换为度数(0到360)。当我们得到角度值,就可以点亮相应的LED灯来指向特定方向。本例中LED指向的方向是北。因此,无论您身在何处,电路板上只会有一个LED发光,LED的方向表示NORTH方向。


在本篇文章的末尾处列出了数字罗盘的完整代码。您可以在包含库后直接将代码上传到您的开发板上,然后就可以开始使用了。但是,如果您想进一步了解代码是如何处理的,请进一步阅读。


如前所述,我们使用的是QMC5883L,要想与该IC通信,需要知道其寄存器的I2C地址,这可以在其数据手册中找到。幸运的是,我们所有这一切都已经完成,并被一个名为keepworking在Github上的人打包成一个库。因此,您只需通过单击链接获取ZIP文件,即可下载QMC5883L库。然后,可以通过以下草图 - >包含库 - >添加.ZIP库将此ZIP文件添加到Arduino IDE中。


添加库后,我们可以了解程序。首先程序中包含所需的库文件,如下所示。wire库用于启用I2C通信,MechaQMC5883库是我们刚刚添加到Arduino的那个。该库包含有关如何与EMC5883L传感器通信的所有信息。

  1. #include <Wire.h> //Wire Librarey for I2C communication
  2. #include <MechaQMC5883.h> //QMC5883 Librarey is added since mine is QMC583 and not HMC5883
复制代码

在接下来的代码行中,我们为使用的传感器创建一个对象。我使用的名称是qmc,但它可以是其他名字。

  1. MechaQMC5883 qmc; //Create an object name for the snsor, I have named it as qmc
复制代码

接下来,我们介绍全局变量声明。这里由于我们有8个Led作为输出,很难通过引脚名称来引用每个引脚,因此我们使用数组选项来引用所有LED。数组的名称是ledPins,变量led_count是我们拥有的led数。它从0开始。

  1. int ledPins[] = {2,3,4,5,6,7,8,9}; //Array of output pin to which the LED is connected to
  2. char led_count = 7; //Total number of LED pins
复制代码

在void setup函数中,我们初始化I2C通信、串行通信和传感器。然后将所有LED引脚声明为输出引脚。由于我们使用了一个数组,因此很容易通过使用for循环并在for循环中导航来引用所有引脚,如下所示。

  1. void setup() {
  2.   Wire.begin(); //Begin I2C communication
  3.   Serial.begin(9600); //Begin Serial Communication
  4.   qmc.init(); //Initialise the QMC5883 Sensor

  5.   for (int thisPin=0; thisPin <= led_count; thisPin++){ //Navigate through all the pins in array
  6.     pinMode(ledPins[thisPin],OUTPUT); //Declare them as output
  7.   }
  8. }
复制代码

在主循环中,我们必须从传感器获取、y和z的值,并计算传感器当前所面向的角度。要读取x、y和z的值,请使用以下代码

  1. int x,y,z;
  2. qmc.read(&x,&y,&z); //Get the values of X,Y and Z from sensor
复制代码

计算出角度数的公式如下所示。由于我们不打算沿z轴旋转指南针,因此我们不考虑该值。只有当IC平面朝向我们的设置时,才能使用此公式。一旦计算了航向,该值将在-180到180的范围内,我们必须将其转换为0到360,就像我们在所有数字罗盘中找到的那样。

  1. int heading=atan2(x, y)/0.0174532925; //Calculate the degree using X and Y parameters with this formulae
  2. //Convert result into 0 to 360
  3.   if(heading < 0)
  4.   heading+=360;
  5.   heading = 360-heading;
复制代码

最后一步是使指向北方向的LED发光。为此,我们有一系列if条件语句,我们检查当前角度值的范围,然后根据它点亮LED。代码如下所示

  1. //Based on the value of heading print the result for debugging and glow the respective LED.
  2.   if (heading > 338 || heading < 22)
  3.   {
  4.     Serial.println("NORTH");
  5.     digitalWrite(ledPins[0],HIGH);
  6.   }

  7.   if (heading > 22 && heading < 68)
  8.   {
  9.     Serial.println("NORTH-EAST");
  10.     digitalWrite(ledPins[7],HIGH);
  11.   }

  12.   if (heading > 68 && heading < 113)
  13.   {
  14.     Serial.println("EAST");
  15.     digitalWrite(ledPins[6],HIGH);
  16.   }

  17.   if (heading > 113 && heading < 158)
  18.   {
  19.     Serial.println("SOUTH-EAST");
  20.     digitalWrite(ledPins[5],HIGH);
  21.   }

  22.   if (heading > 158 && heading < 203)
  23.   {
  24.     Serial.println("SOUTH");
  25.     digitalWrite(ledPins[4],HIGH);
  26.   }

  27.   if (heading > 203 && heading < 248)
  28.   {
  29.     Serial.println("SOTUH-WEST");
  30.     digitalWrite(ledPins[3],HIGH);
  31.   }

  32.   if (heading > 248 && heading < 293)
  33.   {
  34.     Serial.println("WEST");
  35.     digitalWrite(ledPins[2],HIGH);
  36.   }

  37.   if (heading > 293 && heading < 338)
  38.   {
  39.     Serial.println("NORTH-WEST");
  40.     digitalWrite(ledPins[1],HIGH);
  41.   }
复制代码

通过查看下表可以理解代码值背后的逻辑。基本上我们计算出我们面向的方向并预测北方并使相应的LED发光。

方向
与Direction相对应的角度
该方向的范围
0°/ 360°
> 338°或<22°
东北
45°
22°至68°
90°
68°至113°
东南
135°
113°至158°
180°
158°至203°
西南
225°
203°至248°
西
270℃
248°至293°
西北
315°
293°至338°

该程序的最后一部分是设置结果的更新速度。我已经创建了一个500毫秒的延迟,然后关闭所有的LED再次从void循环内部的第一个开始。但如果您需要更快的更新,您可以进一步减少延迟。

  1.   delay(500); // update position of LED for every alf seconds
  2. //Turn off the all the LED
  3.     for (int thisPin=0; thisPin <= led_count; thisPin++){
  4.      digitalWrite(ledPins[thisPin],LOW);
  5.   }
复制代码

测试数字罗盘

我们使用的是Arduino pro mini开发板,所以需要一个类似于FTDI Programmer烧写器上传程序。完成后,您应该注意到一块LED在电路板上发光,LED发光的方向将是NORTH方向。

Testing-Digital-Compass-using-Arduino-and-HMC5883L-Magnetometer.jpg


然后,您可以旋转它,并检查LED是否仍然指向北方向。之后,您可以随时使用9V电池为设备供电,并检查您所面对的方向是否正确。您可能会注意到,当您的电路板附近有重金属片或者沿着Z轴旋转电路板时,这些值会出错。在下一篇文章中,我们将介绍解决方法。


希望你喜欢本篇文章并从中学到一些有用的东西。以下是本篇本篇文章的全部代码: main.rar (1.17 KB, 下载次数: 29)

回复

使用道具 举报

aptx4869
发表于: 2019-12-8 19:33:57 | 显示全部楼层

请问到底是HMC5883L还是QMC5883L?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1480



手机版|

GMT+8, 2024-4-27 01:50 , Processed in 0.040413 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表