【雕爷学编程】Arduino动手做(147)---QMC5883L三轴罗盘模块

37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞不掂的问题,希望能够抛砖引玉。

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271

 

知识点:QMC5883L芯片
源于Honeywell的HMC5883L,是一款表面贴装的集成了信号处理电路的三轴磁性传感器,应用场景主要包括罗盘、导航、无人机、机器人和手持设备等一些高精度的场合。HMC5883是霍尼韦尔公司生产的一款地磁场检测芯片,其国产替代产品为QMC5883。这两种芯片基本相似,QMC 5883也是号称得到了霍尼韦尔公司的授权。 霍尼韦尔的磁传感器在低磁场传感器行业中是灵敏度最高和可靠性最好的传感器。

 

QMC5883L特征
(1)霍尼韦尔(中国)QMC5883L是一款表面贴装多芯片模块,设计用于具有数字接口的低场磁感应,适用于低成本指南针和磁力计等应用
(2)结合低噪声AMR传感器的12位ADC在±8高斯场中实现5毫高斯场分辨率
(3)低电压运行,低功耗; 支持内置的自检
(4)内置式皮带驱动电路,I2C数字接口,宽磁场范围(+/- 8 oe)
(5)工作电压:3.3v-5v; PCB尺寸:1.3 x 2.3厘米(QMC5883L尺寸:3.0 x 3.0 x 0.9毫米),带有16引脚无铅芯片载体(LCC)

 

QMC5883L内部原理图

QMC5883L是一款多芯片三轴磁传感器。 这个表面贴装的小尺寸芯片集成了磁传感器信号条件ASIC,面向高精度应用,例如无人机,机器人,移动设备中的指南针,导航和游戏个人手持设备。

QMC5883L基于最新的高分辨率,霍尼韦尔AMR技术授权的磁阻技术。结合定制设计的16位ADC ASIC,它具有以下优势:低噪声,高精度,低功耗,偏移消除和温度补偿。 QMC5883L启用1°至2°指南针航向精度。 I2C串行总线可简化接口。QMC5883L位于3x3x0.9mm3中表面贴装16针焊盘栅格阵列(LGA)封装。

功能
1、3x3x0.9 mm3中的3轴磁阻传感器陆地栅格阵列封装(LGA),保证在扩展的温度范围内工作-40°C至+85°C。
2、具有低噪声AMR传感器的16位ADC实现2毫高斯场分辨率。
3、宽磁场范围(±8高斯)。
4、温度补偿数据输出和温度输出。
5、具有标准模式和快速模式的I2C接口。
6、宽范围工作电压(2.16V至3.6V)和低功耗(75uA)。
7、无铅封装构造。
8、提供软件和算法支持。

优点
1、体积小,适用于高度集成的产品。 信号有已数字化和校准。
2、启用1°至2°度的罗盘航向精度,允许导航和LBS应用。
3、最大化传感器的完整动态范围和分辨率。
4、在宽广的范围内自动保持传感器的灵敏度工作温度范围。
5、用于快速数据通信的高速接口,最大200Hz数据输出速率。
6、兼容电池供电的应用。
7、符合RoHS标准。
8、可获得罗盘航向、硬磁、软磁以及自动校准库。

 

QMC5883L封装3-D视图 箭头指示在正常测量中产生正输出读数的磁场方向组态。

 

外部连接

双电源连接

单电源连接

 

 

 QMC5883L性能

GY-271 QMC5883L模块 电子指南针罗盘模块 三轴磁场传感器

采用高品质沉金pcb,机器焊接工艺,保证品质

名称:QMC5883L模块(三轴磁场模块)

型号:GY-271使用芯片:QMC5883L

供电电源:3-5v

通信方式:IIC通信协议

测量范围:±1.3-8 高斯

 

该模块包括一个最新的高分辨率QMC5883X系列磁阻传感器,一个包含放大功能的ASIC,自动消磁带驱动器,失调消除以及一个12位ADC,可实现1°至2°的罗盘 航向精度。 I2C串行总线可简化接口。电原理图如下。

 

 

引脚功能

VCC + 5V-电源引脚,给它3.3v-5VDC。 对于Arduino,建议5v

GND-接地引脚

SDA和SCL-这些是I2C数据和时钟引脚,用于从模块向微控制器发送和接收数据。 这些引脚上有1万上拉至3.3v引脚。 您可以将这些引脚连接到5V I2C线路,板上有电平转换器,可将引脚安全降低到3V

DRDY-这是“数据就绪”引脚输出。 如果要高速流传输数据(每秒超过100次),则可以在准备好读取数据时收听此引脚。 有关使用DRDY引脚的更多详细信息,请参见数据表,我们不使用它,因为我们读得不快!

Build the circuit

QMC5883L--------------- Uno/Mega2560

VCC------------------- 5V

GND------------------- GND

SCL------------------- A5/ pin21 mega2560

SDA------------------- A4/pin20 mega2560

DRDY------------------ N/C

 

 

QMC5883L模块的几个定义:

AMR Bridge:三轴磁性传感器

MUX:多路复用通道

PGA:可编程控制的传感器信号增益放大器

Signal Conditioning:进行磁场信号校正及补偿的数字模块

ADC:16位的模数转换器

I2C:总线形式

NVM:用于校正的非易失性存储器

SET/RST Driver:用于初始化磁性传感器的内部驱动

Reference:用于内部偏移的电压/电流基准

Clock Gen.:内部振荡器,用于内部操作

POR:上电复位

Temperature Sensor:用于内部精度/偏移的温度传感器,也可以用于测量温度并输出

QMC5883L有两种工作模式:连续测量模式和待命模式。

 

QMC5883L模块实验接线示意图

 

安装QMC5883库,在网上搜到不少相关的库:
keepworking /Mecha_QMC5883L
https://github.com/keepworking/mecha_qmc5883l

mprograms /QMC5883LCompass
https://github.com/mprograms/QMC5883LCompass

dthain /QMC5883L
https://github.com/dthain/QMC5883L

liyupengsGit /QMC5883LCompass
https://github.com/liyupengsGit/QMC5883LCompass

 

 

Arduino实验开源代码

项目一:简易测量方位角度的实验

 

/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271

 1、安装库:IDE--工具--管理库--搜索“QMC5883L”--安装QMC5883LCompass

 2、项目一:简易测量方位角度(数值在0-359度之间)

 3、实验接线:

 QMC5883L-------------- UNO

 VCC------------------- 5V

 GND------------------- GND

 SCL ------------------- A5

 SDA------------------- A4

 DRDY------------------ N/C

*/



#include <QMC5883LCompass.h>

QMC5883LCompass compass;

void setup() {

 Serial.begin(9600);

 compass.init();

}

void loop() {

 int a;

 // 读取罗盘值

 compass.read();

 // 返回方位角读数

 a = compass.getAzimuth();

 Serial.print("A: ");

 Serial.print(a);

 Serial.println();

 delay(250);

}

  

Arduino实验场景图

 

Arduino实验开源代码

项目二:简易测量方位角度的实验开源代码(数值在0-11之间,二个数值间隔30度)

 

/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271

 1、安装库:IDE--工具--管理库--搜索“QMC5883L”--安装QMC5883LCompass

 2、项目二:简易测量方位角度(数值在0-11之间,每个数值间隔30度)

 3、实验接线:

 QMC5883L-------------- UNO

 VCC------------------- 5V

 GND------------------- GND

 SCL ------------------- A5

 SDA------------------- A4

 DRDY------------------ N/C

*/



#include <QMC5883LCompass.h>

QMC5883LCompass compass;



void setup() {

 Serial.begin(9600);

 compass.init();

}



void loop() {

 compass.read();

 byte a = compass.getAzimuth();

 // 根据方位/方位角的方向,此处的输出将是介于0到11之间的值。

 byte b = compass.getBearing(a);

 Serial.print("B: ");

 Serial.print(b);

 Serial.println();

 delay(250);

}

  实验串口返回情况

知识点:方位角
又称地平经度(Azimuth angle,缩写为Az),是在平面上量度物体之间的角度差的方法之一。是从某点的指北方向线起,依顺时针方向到目标方向线之间的水平夹角,用“度”和“密位”表示。常用于判定方位、指示目标和保持行进方向。

从真子午线起算的为真方位角,通常在精密测量中使用,从磁子午线起算的方磁方位角,在航空、航海、炮兵射击、军队行进时广泛使用,从地形图的坐标纵线起算的为坐标方位角,炮兵使用较多。磁方位角与真方位角的关系式为:磁方位角=真方位角-(±磁偏角)。坐标方位角与磁方位角的关系式为:坐标方位角=磁方位角+ (±磁坐偏角)。

从标准方向的北端起,顺时针方向到直线的水平角称为该直线的方位角。以北点为起算点,由北点开始按顺时针方向计量。方位角的取值范围为0~360度,北点为0°,东点为90°,南点为180°,西点为270°。

QMC5883L Compass是一个Arduino库,用于将QMC5583L系列模块使用指南针(电子罗盘)功能。支持:

1、获取XYZ轴的值。

2、计算方位角。

3、获得16点方位角轴承方向(0-15)。

4、获取16点方位角轴承名称(N,NNE,NE,ENE,E,ESE,SE,SSE,S,SSW,SW,WSW,W,WNW,NW,NNW)

5、通过滚动平均和最小/最大消除来平滑XYZ读数。

6、任选的芯片组模式。

 

Arduino实验开源代码之三

 

/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271

 1、安装库:IDE--工具--管理库--搜索“QMC5883L”--安装QMC5883LCompass

 2、项目三:通过串口实时绘制电子罗盘方位角的波形

 3、实验接线:

 QMC5883L-------------- UNO

 VCC------------------- 5V

 GND------------------- GND

 SCL ------------------- A5

 SDA------------------- A4

 DRDY------------------ N/C

*/



#include <QMC5883LCompass.h>

QMC5883LCompass compass;

void setup() {

 Serial.begin(9600);

 compass.init();

}

void loop() {

 int a;

 // 读取罗盘值

 compass.read();

 // 返回方位角读数

 a = compass.getAzimuth();

 Serial.print("电子罗盘方位角: ");

 Serial.print(a);

 Serial.println();

 delay(800);

}

  

用手转动QMC5883L模块,串口输出的实时波形,数值在0--359°之间波动,简单又直观。

 

串口输出的实时数值

 

QMC5883L Compass 函数的几个使用要点

1、QMC5883L与Arduino Uno / Nano的连接

VCC  O ---- O +5v
GND  O ---- O GND
SCL  O ---- O A5
SDA  O ---- O A4
DRDY O ---- X NOT CONNECTED

  

2、入门
首先,在程序顶部包括QMC5883L指南针库。

#include <QMC5883LCompass.h>
QMC5883LCompass compass;

 

然后在setup()函数中添加:

void setup(){
  compass.init();
}

  

3、获取X,Y或Z轴的数值
要获取X,Y或Z传感器的读数,只需调用所需的功能。

void loop(){
   int x = compass.getX();
   int y = compass.getY();
   int z = compass.getZ();
}

  

4、获取方位角的数值
要获取计算出的方位角(罗盘度)值,只需调用getAzimuth();。

void loop(){
   int a = compass.getAzimuth();
}

 

5、获取方向/方位
QMC5883L指南针库可计算传感器指向的方向范围和方向。您可以调用两个函数。
要获取传感器面向的方向的12点值,可以调用getBearing(azimuth)。这会将罗盘的360度范围划分为12个部分,并按顺时针顺序返回值0-11。在这种情况下,0 = N,3= E,6 = S,9=W。如果您希望滚动自己的方向输出功能而不需要计算,则此功能很有用。

void loop(){
   azimuth = compass.getAzimuth();
   byte b = compass.getBearing(azimuth);
}

  

要获取传感器指向方向的12点文字表示,可以致电getDirection(azimuth);。这将产生一个char数组[3],其中的字母代表每个方向。由于我们无法返回数组,因此需要通过引用传递值。

void loop(){
   azimuth = compass.getAzimuth();
   char myArray[3];
   getDirection(myArray, azimuth);
}

  

如果要打印这些值,可以这样:

void loop(){
   azimuth = compass.getAzimuth();
   char myArray[3];
   
   getDirection(myArray, azimuth);
   
   Serial.print(myArray[0]);
   Serial.print(myArray[1]);
   Serial.print(myArray[2]);
   Serial.println();
}

  

 

6、更改I2C地址
要在调用compass.setADDR(BYTE_VALUE);之前更改I2C地址呼叫,compass.init();如下所示:

void setup(){
  compass.setADDR(BYTE);
  compass.init();
}

  

7、更改模式,数据速率,比例,采样率
您还可以更改QMC5583L芯片的模式,灵敏度,采样率和输出率。等等,只需在调用compass.setMode(MODE, ODR, RNG, OSR);后调用即可compass.init()。请注意,每个值必须是一个字节。设置每个模式的值在预设中,并取自QST QMC5583L数据表。

8、精细QMC5583L传感器输出
在传感器读数似乎反弹的情况下,平滑可以提供帮助。QMC5883L指南针库使用滚动平均值功能来存储(N)个传感器读数并返回每个轴的平均值。该平均还对方位角和方向输出进行平滑处理。

如果启用,该功能的第二部分将采用内部滚动逐步通过的当前替代和替代,将其从总体上中删除。这可以帮助消除在错误的读数中可能发生的替代的高点和低点。

应该注意的是,内置的平滑功能将导致额外的处理时间。

compass.setSmoothing(STEPS, ADVANCED);

  

在循环之前启用平滑调用。

步骤:int,使结果平滑的步骤数。1到10的有效值。更高的步长等于更平滑,但处理时间缩短。

*:启用此功能将使平滑效果更好,但处理时间缩短。*

void setup(){
  compass.init();
  compass.setSmoothing(10, true);
}

  

9、校准QMC5583L传感器
QMC5883LCompass库包含校准功能和实用程序大纲,可帮助您校准QMC5883L芯片。校准是一个两步过程。

步骤1:运行校准程序
a、确保已连接QMC5883L芯片。
b、在示例> QMC5883LCOMPASS>校准下找到随附的校准草图。
c、将校准草图上传到您的arduino,然后打开串行监视器。
d、校准过程开始时,通过移动传感器来伴随屏幕上的指示。
c、收集完所有校准数据后,复制副本的代码

compass.setCalibration(-1537, 1266, -1961, 958, -1342, 1492);

  

可能需要保存它以备将来参考。

步骤2:使用校正资料
a、项目的程序,将然后复制的代码行直接插入到compass.init()调用下方。
b、照常使用QMC5883LCompass库。
建议您使用提供的校准草图来生成传感器的预设和替代,但也可以使用该

compass.setCalibration(X_MIN, X_MAX, Y_MIN, Y_MAX, Z_MIN, Z_MAX);

  

函数添加自己的预设和替代。

 

实验开源代码

项目四:通过串口实时绘制电子罗盘方位(12等分)的波形

说明:实时数值 0 = N,3 = E,6 = S,9 =W

 

/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

 实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271

 1、安装库:IDE--工具--管理库--搜索“QMC5883L”--安装QMC5883LCompass

 2、项目四:通过串口实时绘制电子罗盘方位(12等分)的波形

 3、实验接线:

 QMC5883L-------------- UNO

 VCC------------------- 5V

 GND------------------- GND

 SCL ------------------- A5

 SDA------------------- A4

 DRDY------------------ N/C

 4、说明:实时数值 0 = N,3 = E,6 = S,9 =W

*/



#include <QMC5883LCompass.h>

QMC5883LCompass compass;

void setup() {

 Serial.begin(9600);

 compass.init();

}

void loop() {

 compass.read();

 byte a = compass.getAzimuth();

 // 根据方位/方位角的方向,此处的输出将是介于0到11之间的值。

 byte b = compass.getBearing(a);

  

 Serial.print("指南针方位: ");

 Serial.print(b);

 Serial.println();

  

 delay(800);

}

  

用手转动QMC5883L模块,串口输出的指南针方位数值变动实时波形

 

串口输出的指南针方位数值

 

 

做了一个指南针方位示意图

本实验指南针方位的取值范围为0~11,北点为0,东点为3,南点为6,西点为9。东(duEast)、西(West)、南(zhiSouth)、北dao(North)这四个方向的字母表示,是根据他们的英文单词的首字母来确定的。

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271

  安装库:IDE--工具--管理库--搜索“QMC5883L”--安装  QMC5883LCompass

  项目:室内测量方位角度(数值在0-359度之间)

  实验开源代码

 

/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

 实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271

 1、安装库:IDE--工具--管理库--搜索“QMC5883L”--安装QMC5883LCompass

 2、项目:简易测量方位角度(数值在0-359度之间)

 3、实验接线:

 QMC5883L-------------- UNO

 VCC------------------- 5V

 GND------------------- GND

 SCL ------------------- A5

 SDA------------------- A4

 DRDY------------------ N/C

*/



#include <QMC5883LCompass.h>

QMC5883LCompass compass;

void setup() {

 Serial.begin(9600);

 compass.init();

}

void loop() {

 int a;

 // 读取罗盘值

 compass.read();

 // 返回方位角读数

 a = compass.getAzimuth();

 Serial.print("地磁方位角: ");

 Serial.print(a);

 Serial.print("°");

 Serial.println();

 delay(500);

}

  

实验串口返回情况

Arduino实验场景图

 

实验串口绘图器返回情况  

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271

  项目之六:测试方向

  实验开源代码

 

/*

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)

 实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271

 项目之六:测试方向

 实验接线:

 QMC5883L-------------- UNO

 VCC------------------- 5V

 GND------------------- GND

 SCL ------------------- A5

 SDA------------------- A4

 DRDY------------------ N/C

*/



#include <QMC5883LCompass.h>

QMC5883LCompass compass;

void setup() {

 Serial.begin(9600);

 compass.init();

}

void loop() {

 compass.read();

 byte a = compass.getAzimuth();

 char myArray[3];

 compass.getDirection(myArray, a);

 Serial.print(myArray[0]);

 Serial.print(myArray[1]);

 Serial.print(myArray[2]);

 Serial.println();

 delay(250);

}

  

实验串口返回情况

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
项目之七:三轴XYZ实时数据

实验开源代码

/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
 实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
  项目之七:三轴XYZ实时数据
  实验接线:
  5883L-------------- UNO
  VCC------------------- 5V
  GND------------------- GND
  SCL ------------------- A5
  SDA------------------- A4
  DRDY------------------ N/C
*/

#include <QMC5883LCompass.h>

QMC5883LCompass compass;

void setup() {
  Serial.begin(9600);
  Serial.print("5883L准备就绪");
  compass.init();

  /*
     调用 setSmoothing(STEPS, ADVANCED);

     STEPS = int 平滑结果的步数。有效 1 到 10。
     更高的步骤等于更平滑但更长的处理时间。

     ADVANCED = bool 打开或关闭高级平滑。True 将从每个步骤中删除最大值和最小值,然后正常处理。
     启用此功能将导致更加平滑,但需要更长的处理时间。

  */
  compass.setSmoothing(10, true);
}

void loop() {
  int x, y, z;

  // Read compass values
  compass.read();

  // Return XYZ readings
  x = compass.getX();
  y = compass.getY();
  z = compass.getZ();

  Serial.print("X: ");
  Serial.print(x);
  Serial.print(" Y: ");
  Serial.print(y);
  Serial.print(" Z: ");
  Serial.print(z);
  Serial.println();

  delay(250);
}

  

实验串口返回情况

实验串口绘图器返回情况

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
项目之八:简单的QMC5883L 指南针演示
实验开源代码

 

/*
 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
   实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
   项目之八:简单的QMC5883L 指南针演示
   实验接线:
   5883L-------------- UNO
   VCC------------------- 5V
   GND------------------- GND
   SCL ------------------- A5
   SDA------------------- A4
   DRDY------------------ N/C
*/

#include <QMC5883L.h>
#include <Wire.h>

QMC5883L compass;

void setup() {
  Wire.begin();

  compass.init();
  compass.setSamplingRate(50);

  Serial.begin(9600);
  Serial.println("QMC5883L 指南针演示");
  Serial.println("向各个方向转动罗盘来校准....");
}

void loop(){
  int heading = compass.readHeading();
  if (heading == 0) {
    /* Still calibrating, so measure but don't print */
  } else {
    Serial.println(heading);
  }
  delay(250);
}

  实验串口返回情况

 

 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
   实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
   项目之九:动态四组数据,xyz+方位角a

  实验开源代码

 

/*
 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
   实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
   项目之九:动态四组数据,xyz+方位角
   实验接线:
   5883L-------------- UNO
   VCC------------------- 5V
   GND------------------- GND
   SCL ------------------- A5
   SDA------------------- A4
   DRDY------------------ N/C
*/

#include <Wire.h>
#include <MechaQMC5883.h>

MechaQMC5883 qmc;

void setup() {
  Wire.begin();
  Serial.begin(9600);
  qmc.init();
  //qmc.setMode(Mode_Continuous,ODR_200Hz,RNG_2G,OSR_256);
}

void loop() {
  int x, y, z;
  int azimuth;
  //float azimuth; //is supporting float too
  qmc.read(&x, &y, &z, &azimuth);
  //azimuth = qmc.azimuth(&y,&x);//you can get custom azimuth
  Serial.print("x: ");
  Serial.print(x);
  Serial.print(" y: ");
  Serial.print(y);
  Serial.print(" z: ");
  Serial.print(z);
  Serial.print(" a: ");
  Serial.print(azimuth);
  Serial.println();
  delay(800);
}

  

实验串口返回情况

实验串口绘图器返回情况

 

模块实验接线示意图
 
 

磁偏角(magnetic declination)
地磁偏角是指地球上任一处的磁北方向和正北方向之间的夹角。当地磁北向实际偏东时,地磁偏角为正,反之为负。地磁偏角在历史上最早由中国北宋科学家沈括记录在著作《梦溪笔谈》中:“方家以磁石磨针锋,则能指南,然常微偏东,不全南也。”而西方最早的记录则在此之后约400年。在地球上不同的地方,地磁偏角一般也不相同。在同一个地方,地磁偏角随着时间的推移也在不断变化。发生磁暴时和在磁力异常地区,如磁铁矿和高压线附近,地磁偏角将会产生急剧变化。在中国大陆的大部分地区,地磁偏角在-10°~+2°之间。在台湾则是-4°~-3°左右。正北(真北TN):

 

方格北(图北GN):以方格北线所测之方位角为方格方位角。
磁北(MN):地磁偏角:当地磁北向实际偏东时,地磁偏角为正,反之为负。

指北针指的方向是磁北(MN),假定磁偏角为偏东14度(14°E) ,正北(TN)会在磁北(MN)右边14度。xx°E:正北在磁北右边xx度。xx°W:正北在磁北左边xx度。

磁偏角是根据您当前位置应用的校正
为了从磁北得到真北,它因地而异。
例子:
基督城,东经 23° 35'
惠灵顿 , 22° 14' EAST
但尼丁,东经 25° 8'
奥克兰,东经 19° 30'

您所在地区的磁偏角可以从​​ http://www.magnetic-declination.com/ 获得

实际测量几个地方的磁偏角

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
项目之十:根据当前位置来校正磁偏角

实验开源代码

 

/*
 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
   实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
   项目之十:根据当前位置来校正磁偏角
   实验接线:
   5883L-------------- UNO
   VCC------------------- 5V
   GND------------------- GND
   SCL ------------------- A5
   SDA------------------- A4
   DRDY------------------ N/C
*/

#include <Arduino.h>
#include <Wire.h>
#include <HMC5883L_Simple.h>

// Create a compass
HMC5883L_Simple Compass;

void setup() {
  Serial.begin(9600);
  Wire.begin();

  // Magnetic Declination is the correction applied according to your present location
  // in order to get True North from Magnetic North, it varies from place to place.
  //
  // The declination for your area can be obtained from http://www.magnetic-declination.com/
  // Take the "Magnetic Declination" line that it gives you in the information,
  //
  // Examples:
  //   Christchurch, 23° 35' EAST
  //   Wellington  , 22° 14' EAST
  //   Dunedin     , 25° 8'  EAST
  //   Auckland    , 19° 30' EAST
  //
  Compass.SetDeclination(-0, 23, 'W');

  //   The device can operate in SINGLE (default) or CONTINUOUS mode
  //   SINGLE simply means that it takes a reading when you request one
  //   CONTINUOUS means that it is always taking readings
  //   for most purposes, SINGLE is what you want.
  Compass.SetSamplingMode(COMPASS_CONTINUOUS);

  //   The scale can be adjusted to one of several levels, you can probably leave it at the default.
  //   Essentially this controls how sensitive the device is.
  //   Options are 088, 130 (default), 190, 250, 400, 470, 560, 810
  //   Specify the option as COMPASS_SCALE_xxx
  //   Lower values are more sensitive, higher values are less sensitive.
  //   The default is probably just fine, it works for me.  If it seems very noisy
  //  (jumping around), incrase the scale to a higher one.
  Compass.SetScale(COMPASS_SCALE_250);

  //   The compass has 3 axes, but two of them must be close to parallel to the earth's surface to read it,
  //   (we do not compensate for tilt, that's a complicated thing) - just like a real compass has a floating
  //   needle you can imagine the digital compass does too.
  //
  //   To allow you to mount the compass in different ways you can specify the orientation:
  //   COMPASS_HORIZONTAL_X_NORTH (default), the compass is oriented horizontally, top - side up. when pointing North the X silkscreen arrow will point North
  //   COMPASS_HORIZONTAL_Y_NORTH, top-side up, Y is the needle,when pointing North the Y silkscreen arrow will point North
  //   COMPASS_VERTICAL_X_EAST,    vertically mounted (tall) looking at the top side, when facing North the X silkscreen arrow will point East
  //   COMPASS_VERTICAL_Y_WEST,    vertically mounted (wide) looking at the top side, when facing North the Y silkscreen arrow will point West
  Compass.SetOrientation(COMPASS_HORIZONTAL_X_NORTH);
}

// Our main program loop.
void loop() {
  float heading = Compass.GetHeadingDegrees();

  Serial.print("Heading: \t");
  Serial.println( heading );
  delay(500);
}

  

实验串口返回情况
项目之十实验说明:这是第二次无法完成磁偏角的校准
第一次是使用QMC5883L的库,这次是使用HMC5883L的库,而实验采用模块的芯片是国产的DB5883L
这是三种有一定差异的不同产家的芯片,估计是在校准程序上有些不能兼容,其他功能还没有发现不兼容的情况。

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
项目十一:使用Adafruit库的HMC5883 磁力计测试

实验开源代码

 

/*
 【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
   实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
   项目十一:使用Adafruit库的HMC5883 磁力计测试
   实验接线:
   5883L-------------- UNO
   VCC------------------- 5V
   GND------------------- GND
   SCL ------------------- A5
   SDA------------------- A4
   DRDY------------------ N/C
*/

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(666666);

void displaySensorDetails(void)
{
  sensor_t sensor;
  mag.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" uT");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" uT");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" uT");
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

void setup(void)
{
  Serial.begin(9600);
  Serial.println("HMC5883 Magnetometer Test"); Serial.println("");

  /* Initialise the sensor */
  if (!mag.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while (1);
  }

  /* Display some basic information on this sensor */
  displaySensorDetails();
}

void loop(void)
{
  /* Get a new sensor event */
  sensors_event_t event;
  mag.getEvent(&event);

  /* Display the results (magnetic vector values are in micro-Tesla (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");

  // Hold the module so that Z is pointing 'up' and you can measure the heading with x&y
  // Calculate heading when the magnetometer is level, then correct for signs of axis.
  float heading = atan2(event.magnetic.y, event.magnetic.x);

  // Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
  // Find yours here: http://www.magnetic-declination.com/
  // Mine is: -13* 2' W, which is ~13 Degrees, or (which we need) 0.22 radians
  // If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
  float declinationAngle = 0.1;
  heading += declinationAngle;

  // Correct for when signs are reversed.
  if (heading < 0)
    heading += 2 * PI;

  // Check for wrap due to addition of declination.
  if (heading > 2 * PI)
    heading -= 2 * PI;

  // Convert radians to degrees for readability.
  float headingDegrees = heading * 180 / M_PI;

  Serial.print("Heading (degrees): "); Serial.println(headingDegrees);

  delay(500);
}

  

实验串口返回情况

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
项目十二:使用简单的代码扫描三轴磁场传感器GY-271的 I2C 地址

实验开源代码

 

/*
   【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
   实验一百五十八:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
   项目十二:使用简单的代码扫描三轴磁场传感器GY-271的 I2C 地址
   实验接线:
   5883L-------------- UNO
   VCC------------------- 5V
   GND------------------- GND
   SCL ------------------- A5
   SDA------------------- A4
   DRDY------------------ N/C
*/

#include <Wire.h> //include Wire.h library

void setup()
{
  Wire.begin(); // Wire communication begin
  Serial.begin(9600); // The baudrate of Serial monitor is set in 9600
  while (!Serial); // Waiting for Serial Monitor
  Serial.println("\nI2C Scanner");
}

void loop()
{
  byte error, address; //variable for error and I2C address
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for (address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.print(address, HEX);
      Serial.println("  !");
      nDevices++;
    }
    else if (error == 4)
    {
      Serial.print("Unknown error at address 0x");
      if (address < 16)
        Serial.print("0");
      Serial.println(address, HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000); // wait 5 seconds for the next I2C scan
}

  

实验串口返回情况

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
项目十三:尝试不使用驱动库来读取XYZ

实验开源代码

 

/*
   【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
   实验一百五十八:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
   项目十三:尝试不使用驱动库来读取XYZ
   实验接线:
   5883L-------------- UNO
   VCC------------------- 5V
   GND------------------- GND
   SCL ------------------- A5
   SDA------------------- A4
   DRDY------------------ N/C
*/


#include <Wire.h> //I2C Arduino Library

#define HMC5883L_ADDR 0x0D //0011110b, I2C 7bit address of HMC5883

bool haveHMC5883L = false;

bool detectHMC5883L ()
{
  // read identification registers
  Wire.beginTransmission(HMC5883L_ADDR); //open communication with HMC5883
  Wire.write(10); //select Identification register A
  Wire.endTransmission();
  Wire.requestFrom(HMC5883L_ADDR, 3);
  if(3 == Wire.available()) {
    char a = Wire.read();
    char b = Wire.read();
    char c = Wire.read();
    if(a == 'H' && b == '4' && c == '3')
      return true;
  }

  return false;
}

void setup()
{
  //Initialize Serial and I2C communications
  Serial.begin(9600);
  Serial.println("GY271 TEST");
  Wire.begin();
  // lower I2C clock http://www.gammon.com.au/forum/?id=10896
  TWBR = 78;  // 25 kHz 
  TWSR |= _BV (TWPS0);  // change prescaler  
}

void loop()
{
  bool detect = detectHMC5883L();

  if(!haveHMC5883L) 
  {
    if(detect) 
    {
      haveHMC5883L = true;
      Serial.println("We have HMC5883L, moving on");
      // Put the HMC5883 IC into the correct operating mode
      Wire.beginTransmission(HMC5883L_ADDR); //open communication with HMC5883
      Wire.write(0x02); //select mode register
      Wire.write(0x00); //continuous measurement mode
      Wire.endTransmission();
    }
    else
    {  
      Serial.println("No HMC5883L detected!");
      delay(2000);
      return;
    }
  }
  else
  {
    if(!detect) {
      haveHMC5883L = false;
      Serial.println("Lost connection to HMC5883L!");
      delay(2000);
      return;
    }
  }
  
  int x,y,z; //triple axis data

  //Tell the HMC5883 where to begin reading data
  Wire.beginTransmission(HMC5883L_ADDR);
  Wire.write(0x0D); //select register 3, X MSB register
  Wire.endTransmission();

 //Read data from each axis, 2 registers per axis
  Wire.requestFrom(HMC5883L_ADDR, 6);
  if(6<=Wire.available()){
    x = Wire.read()<<8; //X msb
    x |= Wire.read(); //X lsb
    z = Wire.read()<<8; //Z msb
    z |= Wire.read(); //Z lsb
    y = Wire.read()<<8; //Y msb
    y |= Wire.read(); //Y lsb
  }
  
  //Print out values of each axis
  Serial.print("x: ");
  Serial.print(x);
  Serial.print("  y: ");
  Serial.print(y);
  Serial.print("  z: ");
  Serial.println(z);
  
  delay(250);
}

  实验串口返回情况(未能识别国产芯片)

 

【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验一百四十七:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
项目十四:QMC5883LCompass三轴磁力计罗盘传感器

实验开源代码

 

/*
   【Arduino】168种传感器模块系列实验(资料代码+图形编程+仿真编程)
   实验一百五十八:QMC5883L电子指南针罗盘模块 三轴磁场传感器GY-271
   项目十四:QMC5883LCompass三轴磁力计罗盘传感器
   实验接线:
   5883L-------------- UNO
   VCC------------------- 5V
   GND------------------- GND
   SCL ------------------- A5
   SDA------------------- A4
   DRDY------------------ N/C
*/

#include <QMC5883LCompass.h>
QMC5883LCompass compass;

void setup(void) {
  // start serial port
  Serial.begin(115200);
  Serial.println("\n\n\nQMC5883 磁力计测试");
  Serial.println("");
  
  compass.init(); 
}

void loop() {
int x, y, z, a, b;
  char myArray[3];
  
  compass.read();
  
  x = compass.getX();
  y = compass.getY();
  z = compass.getZ();
  a = compass.getAzimuth();
  b = compass.getBearing(a);
  compass.getDirection(myArray, a);
    
  Serial.print("X: ");
  Serial.print(x);

  Serial.print(" Y: ");
  Serial.print(y);

  Serial.print(" Z: ");
  Serial.print(z);

  Serial.print(" 方位角: ");
  Serial.print(a);

  Serial.print(" 方位: ");
  Serial.print(b);

  Serial.print(" 方向: ");
  Serial.print(myArray[0]);
  Serial.print(myArray[1]);
  Serial.print(myArray[2]);
  Serial.println();
  delay(500);
}

  

实验串口返回情况

 

实验串口绘图器返回情况

 

Arduino实验场景图

 

 

 

posted @ 2023-07-01 07:52  行者花雕  阅读(671)  评论(0编辑  收藏  举报