使用Arduino和HMC5883L磁力计的数字罗盘

原文:https://circuitdigest.com/microcontroller-projects/digital-compass-with-arduino-and-hmc5883l-magnetometer

使用Arduino和HMC5883L磁力计的数字罗盘

ARDUINO的

经过**阿斯温斯·拉吉(Aswinth Raj)** 2018年11月6日
在这里插入图片描述

人脑由复杂的结构层构成,可帮助我们成为地球上的优势物种。例如,大脑中的内嗅皮层可以为您提供方向感,帮助您轻松导航到您不熟悉的地方。但是与我们不同的是,机器人和无人驾驶Ariel车辆需要某种东西来获得这种方向感,以便他们能够在新的地形和风景中自动进行操纵。不同的机器人使用不同类型的传感器来完成此任务,但是最常用的是磁力计,它可以告知机器人当前所处的地理方向。这不仅可以帮助机器人感应方向,还可以按照预定的方向和角度转弯。

由于传感器可以指示北,南,东和西的地理信息,因此我们人类也可以在需要时使用它。因此,在本文中,让我们尝试了解磁力计传感器的工作原理以及如何将其与Arduino等微控制器接口。在这里,我们将构建一个很酷的数字罗盘,它会通过发出指向北方向的LED来帮助我们找到方向。这款数字指南针是由PCBGOGO精巧地在PCB上制成的,以便下次野外出行时可以携带它,并希望我迷路只是为了用这个东西找到回家的路。让我们开始吧。

Arduino指南针项目所需的材料

  • Arduino Pro迷你版
  • HMC5883L磁力计传感器
  • LED灯-8号
  • 470Ohm电阻器– 8号
  • 桶杰克
  • 像PCBgogo这样的可靠PCB制造商
  • 迷你FTDI编程器
  • 电脑/笔记本电脑

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

在深入探讨电路之前,让我们先了解一下磁力计及其工作原理。顾名思义,“电磁”一词并不是指奇迹中那种疯狂的突变体,他可以通过在空中弹钢琴来控制金属。哦!但是我喜欢那个他很酷的家伙。

磁力计实际上是一种设备,可以感应地球的磁极并据此指出方向。众所周知,地球是一块带有北极和南极的球形磁铁。并因此而产生磁场。磁力计感测到该磁场,并根据磁场的方向可以检测出我们所面对的方向。

HMC5883L传感器模块如何工作

作为磁力计传感器HMC5883L具有相同的功能。它上面有霍尼韦尔(中国)的HMC5883L IC。该IC具有3种磁阻材料,它们沿x,y和z轴排列。流过这些材料的电流量对地球磁场很敏感。因此,通过测量流过这些材料的电流的变化,我们可以检测到地球磁场的变化。一旦吸收了磁场的变化,就可以通过I2C协议将这些值发送到任何嵌入式控制器,例如微控制器或处理器。

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

HMC5883L和QMC5883L之间的区别

对于许多初学者来说,围绕这些传感器存在一个普遍的困惑。这是因为某些供应商(实际上是大多数供应商)出售了QMC5883L传感器,而不是霍尼韦尔的原始HMC5883L。这主要是因为QMC5883L比HMC5883L模块便宜。可悲的是,这两个传感器的工作方式略有不同,并且不能对两个传感器使用相同的代码。这是因为两个传感器的I2C地址不同。本教程中给出的代码仅适用于QMC5883L常用的传感器模块。
在这里插入图片描述
磁力计QMC5883L

要知道您所使用的传感器型号,您只需仔细查看IC本身,以读取上面写的内容。如果写的是类似L883的东西,那就是HMC58836L;如果写的是类似DA5883的话,那就是QMC5883L IC。下图显示了这两个模块,以方便进行低估。
在这里插入图片描述

Arduino数字指南针电路图

基于Arduino的Digital Compass的电路非常简单,我们只需要将HMC5883L传感器与Arduino接口并将8个LED连接到Arduino Pro mini的GPIO引脚即可。完整的电路图如下所示
在这里插入图片描述
传感器模块具有5个引脚出其中的DRDY(数据准备好)未在我们的项目,因为我们正在操作在连续模式中的传感器使用。Vcc和接地引脚用于从Arduino板以5V为模块供电。的SCL和SDA是I2C通信总线线路分别连接到Arduino临迷你的A4和A5 I2C引脚。由于模块本身在线路上具有上拉电阻,因此无需在外部添加它们。

为了说明方向,我们使用了8个LED,它们全部通过470欧姆的限流电阻连接到Arduino的GPIO引脚。完整电路由9V电池通过桶形插孔供电。该9V直接提供给Arduino的Vin引脚,并使用Arduino上的板载稳压器将其调节为5V。然后使用此5V电压为传感器和Arduino供电。

制作用于数字罗盘的PCB

电路的想法是将8个LED圆形放置,以便每个LED指向所有8个方向,分别是北,东北,东,东南,南,西南,西和西北。因此,就此而言,将它们整齐地排列在面包板上或什至在穿孔板上是不容易的。为该电路开发PCB将使其看起来更整洁且易于使用。因此,我打开了PCB设计软件,将LED和电阻器排列成整齐的圆形图案,并连接了走线以形成连接。完成后,我的设计如下所示。您也可以从下面给出的链接下载Gerber文件。

  • 下载用于数字罗盘PCB的Gerber文件
    在这里插入图片描述
    我将其设计为双面板,因为我希望将Arduino放在PCB的底部,以免破坏PCB顶部的外观。如果您担心必须为双面PCB付出高昂的价格,那么请耐心等待。

现在,我们的设计已经准备就绪,是时候制作它们了。要完成PCB非常简单,只需执行以下步骤

第1步: 进入www.pcbgogo.com,如果这是您第一次,请注册。然后,在“ PCB原型”选项卡中,输入PCB的尺寸,层数和所需的PCB数。我的PCB是80cm×80cm,所以标签如下
在这里插入图片描述

*第2步:单击立即报价***按钮继续。您将进入一个页面,在该页面上可以根据需要设置一些其他参数,例如使用的轨道间距等材料。但是大多数情况下,默认值都可以正常工作。我们在这里唯一需要考虑的是价格和时间。如您所见,构建时间仅为2-3天,而我们的PSB只需花费$ 5。然后,您可以根据需要选择一种首选的运输方式。
在这里插入图片描述

**步骤3:**最后一步是上传Gerber文件并继续付款。为确保流程顺利进行,PCBGOGO在继续付款之前会验证您的Gerber文件是否有效。这样,您可以确保您的PCB易于制造,并且能够按承诺达到您的要求。

组装PCB

订购该板后,几天后便到达了我手中,尽管快递员装在贴有整齐标签的包装好的盒子中,而且像往常一样,PCB的质量很棒。我分享了以下几张木板的图片,供您判断。
在这里插入图片描述
我打开了焊锡棒,开始组装电路板。由于脚印,焊盘,通孔和丝网印刷的形状和尺寸都非常合适,因此我组装电路板没有问题。拆箱后仅需10分钟即可准备好板子。

焊接后板子的几张图如下所示。
在这里插入图片描述

编程Arduino

现在我们的硬件已经准备好了,让我们研究一下必须上载到Arduino板上的程序。该代码的目的是从QMC5883L磁力计传感器读取数据并将其转换为度数(0到360)。一旦知道了度数,就必须打开指向特定方向的LED。我在此程序中使用的方向是北。因此,无论您身在何处**,板上的LED都会发光,并且LED的方向将指示“北”方向**。一旦可以稍后计算出另一个方向,就可以知道一个方向。

数字指南针项目的完整代码可在此页面的末尾找到。包含库之后,您可以直接将其上载到板上,并且可以开始使用了。但是,如果您想进一步了解代码中实际发生的情况,请进一步阅读。

如前所述,我们正在使用QMC5883L IC,要与该IC通信,我们需要知道其寄存器的I2C地址,该地址可在其数据表中找到。但幸运的是,所有这些工作已经完成,并由Github上名为keepworking的一个人打包为一个库。因此,您只需单击链接以获取ZIP文件,即可**下载QMC5883L的库**。然后,可以通过遵循Sketch-> Include Library-> Add .ZIP library将这个ZIP文件添加到您的Arduino IDE中。

添加库后,我们可以继续执行程序。我们**通过包含所需的库文件开始该程序,**如下所示。线库用于启用I2C通信,而MechaQMC5883是我们刚刚添加到Arduino的库。该库包含有关如何与EMC5883L传感器通信的所有信息。

#include <Wire.h> //导线库使用用于I2C通信
#include <MechaQMC5883.h> // QMC5883库,自从设备是QMC583而不是HMC5883

在下一行中,我们为正在使用的传感器创建一个对象名称。我用过***qmc***这个名字,但可以是任何您喜欢的名字。

MechaQMC5883 qmc ; //为snsor创建一个对象名称,我将其命名为qmc

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

int ledPins [] = {2,3,4,5,6,7,8,9}; // LED连接到的输出引脚的阵列
char led_count = 7; // LED引脚总数

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

void setup(){ 
  Wire.begin(); //开始I2C通讯
  Serial.begin(9600); //开始串行通讯
  qmc.init(); //初始化QMC5883传感器

  for(int thisPin = 0; thisPin <= led_count; thisPin ++){//遍历数组
    pinMode(ledPins [thisPin],OUTPUT);//将它们中所有引脚声明为输出  } 
}

在无限循环的循环中,我们必须传感器**获取x,y和z的值,**并计算传感器当前面对的程度。要读取x,y和z的值,请使用以下行

int x,y,z; 
qmc.read(&x,&y,&z); //从传感器获取X,Y和Z的值

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

int heading= atan2(x,y)/0.0174532925; //使用带有以下公式的X和Y参数计算度数
//将结果转换为0到360 
  if(heading <0)
  heading + = 360; 
  heading= 360-heading;

最后一步是在辉光北方向的LED指示。为此,我们有一系列if条件语句,其中检查当前度数在什么范围内,并根据该值打开LED。代码如下所示

//根据标题的值打印调试结果,并使相应的LED发光。
if (heading > 338 || heading < 22)
  {
    Serial.println("NORTH");
    digitalWrite(ledPins[0],HIGH);
  }

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

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

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

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

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

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

  if (heading > 293 && heading < 338)
  {
    Serial.println("NORTH-WEST");
    digitalWrite(ledPins[1],HIGH);
  }

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

方向方向对应的度数该方向的范围
0°/ 360°> 338°或<22°
东北45°22°至68°
东方的90°68°至113°
东南部135°113°至158°
180°158°至203°
西南225°203°至248°
西170°248°至293°
西北315°293°至338°

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

  delay(500); 的LED每//更新位置ALF秒
//关闭所有的LED
    for(int thisPin = 0; thisPin <= led_count; thisPin ++){ 
     digitalWrite(ledPins[thisPin],LOW); 
  }

测试数字指南针

因为我们已经使用了Arduino pro mini,所以我们需要一个FTDI板之类的外部编程器来上载程序。上载程序后,您应该注意到板上的一个LED发光,该LED发光的方向将是NORTH方向
在这里插入图片描述

然后,您可以通过旋转面板来进行操作,并检查LED是否仍指向北方向。之后,您可以随时使用9V电池为设置供电,并检查您所面对的方向。可以在下面的视频中找到数字指南针的完整功能。您可能会注意到,如果靠近电路板的地方有一块重金属,或者即使沿Z轴旋转电路板,这些值也会出错。有一些方法可以解决此问题,这是另一篇教程。

希望您喜欢本教程并从中学到了一些有用的东西。如果是,则将积分转给赞助此职位的PCBGOGO,因此请尝试一下您的PCB。像往常一样,将您的想法发表在下面的评论部分。

代码

/*
 * Program for Arduino Digital Compass using QMC5883
 * Project by: Aswinth Raj
 * Dated: 1-11-2018
 * Website: www.circuitdigest.com
 * Lib. from https://github.com/keepworking/Mecha_QMC5883L
 * WARNING: This code works only for QMC5883 Sensor which is commonly being sold as HMC5883 read article to find the actual name of the sensor you have.
 */

#include <Wire.h> //Wire Librarey for I2C communication 
#include <MechaQMC5883.h> //QMC5883 Librarey is added since mine is QMC583 and not HMC5883

MechaQMC5883 qmc; //Create an object name for the snsor, I have named it as qmc

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

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

  for (int thisPin=0; thisPin <= led_count; thisPin++){ //Navigate through all the pins in array 
    pinMode(ledPins[thisPin],OUTPUT); //Declare them as output 
  }

}

void loop() { //Infinite Loop
  int x,y,z;
  qmc.read(&x,&y,&z); //Get the values of X,Y and Z from sensor 
  
  int heading=atan2(x, y)/0.0174532925; //Calculate the degree using X and Y parameters with this formulae 

 //Convert result into 0 to 360
  if(heading < 0) 
  heading+=360;
  heading = 360-heading;
  
  Serial.println(heading); //Print the value of heading in degree for debugging 

//Based on the value of heading print the result for debugging and glow the respective LED.
  if (heading > 338 || heading < 22)
  {
    Serial.println("NORTH");
    digitalWrite(ledPins[0],HIGH);
  }
  if (heading > 22 && heading < 68)
  {
    Serial.println("NORTH-EAST");
    digitalWrite(ledPins[7],HIGH);
  }
  if (heading > 68 && heading < 113)
  {
    Serial.println("EAST");
    digitalWrite(ledPins[6],HIGH);
  }
  if (heading > 113 && heading < 158)
  {
    Serial.println("SOUTH-EAST");
    digitalWrite(ledPins[5],HIGH);
  }
  if (heading > 158 && heading < 203)
  {
    Serial.println("SOUTH");
    digitalWrite(ledPins[4],HIGH);
  }
  if (heading > 203 && heading < 248)
  {
    Serial.println("SOTUH-WEST");
    digitalWrite(ledPins[3],HIGH);
  }
  if (heading > 248 && heading < 293)
  {
    Serial.println("WEST");
    digitalWrite(ledPins[2],HIGH);
  }
  if (heading > 293 && heading < 338)
  {
    Serial.println("NORTH-WEST");
    digitalWrite(ledPins[1],HIGH);
  }

  delay(500); // update position of LED for every alf seconds 
//Turn off the all the LED 
    for (int thisPin=0; thisPin <= led_count; thisPin++){
     digitalWrite(ledPins[thisPin],LOW);
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值