摘要:本文介绍使用HMC5883L电子罗盘模块来辨别方向
在前边制作避障小车的时候,大家可能已经发现,虽然两个轮子的驱动信号是一样的,但是小车可能不走直线,走过一端距离之后,小车就会偏向一边。这是由于电机的个体差异导致的,虽然是同一标准、同一批次生产的电动机,但在电气特性上还是存在着些许的差距,经过比较长距离的累积之后,表现出来的就是两个轮子累计转过的圈数不同,小车就会朝一边偏。
小车跑偏的一个解决办法就是通过长距离的测试,找出两个轮子转速的差距,然后调整控制信号PWM的占空比率,让转速慢的轮子占空比率大一些,而转速快的轮子占空比率小一些,就可以在很大程度上改善这个问题了。这种解决办法要经过很多次的测试,才能找到一个比较满意的参数出来。
那么有没有更好的办法呢?能不能让小车自己知道自己在朝哪个方向行驶,自己进行调整呢?答案当然是肯定的。可以给小车安装一个电子罗盘模块,让小车自己知道自己在朝着哪个方向行驶。
我们知道,地球附近的空间遍布着地磁场,地磁场的方向是从地球的地磁北极(地理南极附近)指向地磁南极(地理北极附近),传统的指南针就是利用了地磁场来辨别方向的。基于HMC5883L芯片的电子罗盘模块同样也是利用了这一原理,它通过测量相互垂直的X轴、Y轴和Z轴的磁场的磁通量大小,因为这三个方向的磁通量的矢量和始终指向地磁南极(地理北极附近),所以,就可以计算出HMC5883L电子罗盘模块的水平方向角了,从而可以确定自己的朝向。
和前面的红外测距模块一样,HMC5833L电子罗盘模块也是通过内部寄存器来和外界交互的,通过这些寄存器可以对其设置,也可以得到模块的测量数据。具体的寄存器如下表:
地址 | 名称 | 访问 | 用途 |
00 | 配置寄存器A | 读/写 | 采样平均数、数据输出速率和测量配置寄存器 |
01 | 配置寄存器B | 读/写 | 增益配置寄存器 |
02 | 模式寄存器 | 读/写 | 测量模式配置寄存器,连续模式/单一模式(默认)。 |
03 | 数据输出X MSB寄存器 | 读 | 通道X测量结果的高位数据。 |
04 | 数据输出X LSB寄存器 | 读 | 通道X测量结果的低位数据。 |
05 | 数据输出Z MSB寄存器 | 读 | 通道Z测量结果的高位数据。 |
06 | 数据输出Z LSB寄存器 | 读 | 通道Z测量结果的低位数据。 |
07 | 数据输出Y MSB寄存器 | 读 | 通道Y测量结果的高位数据。 |
08 | 数据输出Y LSB寄存器 | 读 | 通道Y测量结果的低位数据。 |
09 | 状态寄存器 | 读 | 测量数据状态寄存器。 |
10 | 识别寄存器A | 读 | 用来识别装置 |
11 | 识别寄存器B | 读 | 用来识别装置 |
12 | 识别寄存器C | 读 | 用来识别装置 |
在这里,需要提醒一下,电子罗盘芯片有HMC5883和QMC5883两个系列,其中前者为进口芯片,后者为国产芯片,两者功能相同。但是,这两个芯片的寄存器定义不同,请在使用时确认相关文档。
对于配置寄存器的详细描述,请参考datasheet中的详细说明。
下面来看一下HMC5883L电子罗盘接口的详细说明:
序号 | 引脚 | 含义 |
1 | VCC | 电源正极(3-5V) |
2 | GND | 电源负极 |
3 | SCL | IIC串行时钟线 |
4 | SDA | IIC串行数据线 |
5 | DRDY | 中断引脚,表明数据准备好了 |
寄存器看起来很复杂,实际上大多数情况下都不需要你直接去操作寄存器,因为有人已经给你进行了底层的封装,并提供了相应的库函数。打开“Arduino IDE”,安装HMC5883L电子罗盘模块的库函数,选择“Adafruit HMC5883L Unified”,如下图所示:
同样,使用该库函数还是那基本的几个步骤:
- 实例化对象
- 初始化模块
- 读取测量结果
- 数据处理显示
在这里,比之前复杂的就是数据处理部分,因为HMC5883L电子罗盘模块所返回的测量值,只是X、Z和Y三个方向的磁通量,因此想要计算方向,还要根据测量出来的X和Y以及你所在地的磁偏角来进行计算。具体的计算方法,请参见程序代码。
使用HMC5883L电子罗盘模块的时候,有个特别需要注意的地方是,固定HMC5883L芯片的时候,要保证它的Z轴是向上的,并且芯片处于水平状态,否则测量出来的结果是不正确的。
测试的代码如下:
#include <Wire.h> #include <Adafruit_Sensor.h> #include <Adafruit_HMC5883_U.h> /* 为对象的实例分配一个唯一ID */ Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345); void setup(void) { Serial.begin(115200);
/* 初始化传感器 */ if(!mag.begin()) { /* 未找到传感器,请检查配置...... */ Serial.println("未找到传感器,请检查配置......"); while(1); } } void loop(void) { /* 创建一个传感器数据对象 */ sensors_event_t event; mag.getEvent(&event);
/* 显示磁向量的值 (单位:uT) */ Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print(" "); Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print(" "); Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print(" ");Serial.println("uT"); // 让模块的Z轴向上,并保持模块水平,这样才能得到正确的角度结果 float heading = atan2(event.magnetic.y, event.magnetic.x);
// 在这里,你必须要设置你所在位置的磁偏角,否则计算出来的结果是错误的 // 可以使用这个网站查询你的磁偏角: http://www.magnetic-declination.com/ // 查询到的数值是度,需要转换为弧度 // 如果查不到你的磁偏角,请把这两行注释掉,那样测量结果会有稍微的偏移 float declinationAngle = 0.13; heading += declinationAngle;
// 符号修正 if(heading < 0) heading += 2*PI;
// 修正后,超过360度了 if(heading > 2*PI) heading -= 2*PI;
// 把弧度转换成角度 float headingDegrees = heading * 180/M_PI;
Serial.print("偏离正北方角度: "); Serial.println(headingDegrees);
delay(500); } |
程序中已经增加了详细的注释,如果你是从开始学到现在,相信你是能看懂的,在这里就不再解释了。运行结果如下图所示:
好了,关于HMC5883L电子罗盘模块的基本使用就介绍到这里了。