·寄存器配置部分

HMC5883L模块具有两个配置寄存器,配置寄存器A用来配置该装置设置的数据输出速率和测量配置;配置寄存器 B 设置装置的增益。

模式寄存器则是用来设定装置的操作模式,有连续测量模式,单一测量模式和闲置模式等。具体的情况可以查阅HMC5883L数据手册。

下面我们对HMC5883L的寄存器进行配置。

#define HMC5883_REG_X_MSB 0x03 //输出X寄存器A中存储测量结果中的MSB(高位数据)#define HMC5883_REG_X_LSB 0x04 //输出X寄存器B中存储测量结果中的MSB(低位数据)#define HMC5883_REG_Z_MSB 0x05 //输出Y寄存器A中存储测量结果中的MSB(高位数据)#define HMC5883_REG_Z_LSB 0x06 //输出Y寄存器B中存储测量结果中的MSB(低位数据)#define HMC5883_REG_Y_MSB 0x07 //输出Z寄存器A中存储测量结果中的MSB(高位数据) #define HMC5883_REG_Y_LSB 0x08 //输出Z寄存器B中存储测量结果中的MSB(低位数据) /* CRA */#define HMC5883_REG_CRA_MS_MASK0x03#define HMC5883_REG_CRA_MS_NORAL 0x00 // default#define HMC5883_REG_CRA_MS_XYZ_P 0x01#define HMC5883_REG_CRA_MS_XYZ_N 0x02#define HMC5883_REG_CRA_MS_REV 0x03#define HMC5883_REG_CRA_DO_Hz_MASK 0x1C#define HMC5883_REG_CRA_DO_Hz_0_75 0x00#define HMC5883_REG_CRA_DO_Hz_1_50x04#define HMC5883_REG_CRA_DO_Hz_30x08#define HMC5883_REG_CRA_DO_Hz_7_50x0C#define HMC5883_REG_CRA_DO_Hz_15 0x10 // default#define HMC5883_REG_CRA_DO_Hz_30 0x14#define HMC5883_REG_CRA_DO_Hz_75 0x18#define HMC5883_REG_CRA_DO_Hz_NONE 0x1C#define HMC5883_REG_CRA_MA_MASK0x60#define HMC5883_REG_CRA_MA_AVG_1 0x00#define HMC5883_REG_CRA_MA_AVG_2 0x20#define HMC5883_REG_CRA_MA_AVG_4 0x40#define HMC5883_REG_CRA_MA_AVG_8 0x60 // default#define HMC5883_REG_CRA_RUN_MASK 0x80/* CRB */#define HMC5883_REG_GN_GA_MASK 0xE0#define HMC5883_REG_GN_0_88_G13700x00#define HMC5883_REG_GN_1_30_G10900x20 // default#define HMC5883_REG_GN_1_90_G820 0x40#define HMC5883_REG_GN_2_50_G660 0x60#define HMC5883_REG_GN_4_00_G440 0x80#define HMC5883_REG_GN_4_70_G390 0xA0#define HMC5883_REG_GN_5_60_G330 0xC0#define HMC5883_REG_GN_8_10_G230 0xE0/* MODE */#define HMC5883_REG_MODE_MR_MASK 0x03#define HMC5883_REG_MODE_MR_CON0x00#define HMC5883_REG_MODE_MR_SIG0x01 // default #define HMC5883_REG_MODE_MR_IDLE10x02#define HMC5883_REG_MODE_MR_IDLE20x03/* read addr*/#define HMC5883_ADDR 0X3C/*-------------------------------------------------------------IIC地址:0X3C 配置寄存器A:0X00 (用于配置该装置设置的数据输出速率和测量配置)配置寄存器B: 0X01 (用于设置装置的增益)模式寄存器: 0X02 (用来设定装置的操作模式)---------------------------------------------------------------*/

·从寄存器读取数值

/* IIC read x y z data > buf */I2CWriteNByteVal(IIC_HMC5883,HMC5883_REG_X_MSB,0,0);I2CReadNByte(IIC_HMC5883,6,buf);/* buf > short x y z */x = buf[0];x <<= 8;x |= buf[1];z = buf[2];z <<= 8;z |= buf[3];y = buf[4];y <<= 8;y |= buf[5];

·角度获取及计算

在角度计算公式的使用上,atan2函数+180,atan函数+90;

这里计算的原理就是通过获取的X,Y,Z值代入公式进行计算;笔者这边+360,主要是因为芯片焊在板子上之后,方向与原来的方向反了180度,所以在这里+360如何进行逻辑判断。如果不知道自己的方向有没有相反,可以用手机的指南针功能进行对比。

//atan2求出的angle取值范围为[-180,180]angle_xy = atan2(y,x)*(180/3.14159265)+180;angle_xz = atan2(x,z)*(180/3.14159265)+180;angle_yz = atan2(y,z)*(180/3.14159265)+180;//atan求出的angle取值范围为[-90,90]angle_xy = atan(y,x)*(180/3.14159265)+90;angle_xz = atan(x,z)*(180/3.14159265)+90;angle_yz = atan(y,z)*(180/3.14159265)+90;/* 将芯片焊到板子上时,测量方位时正常方位的反面,因而在原有基础上多加180度旋转,再进行判断 */obj.xy_angle_val = atan2(obj.val_y,obj.val_x) * (180 / 3.14159265) + 360;if(obj.xy_angle_val > 360){obj.xy_angle_val = obj.xy_angle_val - 360;}obj.xz_angle_val = atan2(obj.val_x,obj.val_z) * (180 / 3.14159265) + 360;if(obj.xz_angle_val > 360){obj.xz_angle_val = obj.xz_angle_val - 360;}obj.yz_angle_val = atan2(obj.val_y,obj.val_z) * (180 / 3.14159265) + 360;if(obj.yz_angle_val > 360){obj.yz_angle_val = obj.yz_angle_val - 360;

·通过角度计算方位

这边主要通过东南西北,东北西北东南西南,8个方位各个方位的角度区域来推算出相对应的方向。

/* 通过枚举先定义出8个方位 */enum direction_type_em {DIRECTION_NE = 0,DIRECTION_E,DIRECTION_SE, DIRECTION_S,DIRECTION_SW, DIRECTION_W,DIRECTION_NW, DIRECTION_N,};/* 再通过角度范围判断,赋值相应的枚举值 */unsigned char get_direction(void){if (obj.xz_angle_val >= 22 && obj.xz_angle_val = 68&& obj.xz_angle_val = 112 && obj.xz_angle_val = 158 && obj.xz_angle_val = 202 && obj.xz_angle_val = 248 && obj.xz_angle_val = 292 && obj.xz_angle_val <= 337) {obj.direction = DIRECTION_NW;} else {obj.direction = DIRECTION_N;}return obj.direction;}/* 通过枚举值赋值相应的字符串,实现通过角度判断方位 */char* get_direction_str(){switch(get_direction()) {case DIRECTION_NE: return "NE";case DIRECTION_E:return "E";case DIRECTION_SE: return "SE";case DIRECTION_S:return "S";case DIRECTION_SW: return "SW";case DIRECTION_W:return "W";case DIRECTION_NW: return "NW";case DIRECTION_N:return "N";}return 0;}

·对获取的数据进行校准

众所周知,地球是椭圆的,因而我们获取到的全方位数据并非圆形而是椭圆形。因而我们需要将获取到的数据进行校准成圆形。

//偏移校正Xoffset = (Xmax + Xmin)/2;Yoffset = (Ymax + Ymin)/2;Zoffset = (Zmax + Zmin)/2;//系数校正Kx = 1;Ky = (Xmax - Xmin)/(Ymax - Ymin);Kz = (Xmax - Xmin)/(Zmax - Zmin);//将椭圆模型校准成圆形后,获取的x,y,z值x = Kx * (x - Xoffset);y = Ky * (y - Yoffset);z = Kz * (z - Zoffset);

在经过一系列的参数校正后,我们获取到的数据,经过数据采集分析,数据接近圆形(但并非完全的圆形)

*在磁力计校准过程中,我们可以在校准前用如下方法判断磁力计当前状态是否正确:
磁力计的X轴指向正北时,磁力计的寄存器X轴此时输出最大值
磁力计的X轴指向正南时,X轴应该有最小值。
磁力计的Y轴指向正北时,磁力计的寄存器Y轴此时应该输出最小值;
磁力计的X轴指向正南时,Y轴应该有最大值。

·存在的干扰问题

*硬磁干扰:

硬磁干扰是指固定在磁力计所在机体的表面物质产生的固定方向的干扰。
硬磁干扰会导致磁力计所采集的数据形成的圆球偏离球心。

*软磁干扰:

软磁干扰是指固定在磁力计所在机体的表面物质所产生的混乱地磁场的干扰,也就是磁场干扰的方面不是固定的。
软磁干扰会导致磁力计所采集的数据形成圆球变成椭球。

可能造成干扰的因素:

电路板上的马达和喇叭、
含有铁钴镍等金属材料如:屏蔽罩、螺丝、电阻、LCD背板及外壳

需要注意的事项:

在使用传感器側不要使用含铁磁材料(如铁做的插针、插座以及铁材料的导线),这些材料不仅会干扰被测磁场,而且材料的剩磁会导致零位误差。直接将导线焊在传感器板上,不用接插件渡。

如果想要将芯片手工焊在板子上,那么记住要找个技术好的师傅,这个芯片还是挺考验技术的!此外,如果想要用这块芯片做项目,那么在电路设计的时候,记住连接这块芯片的电容要与数据手册上的数值相对应,否则你可能读不到数据然后怀疑自己的程序有问题。两个电容,一个是4.7uf,一个是0.22uf,注意啦,不一样可能读不出数据。

·HMC5883L与QMC5883L的区别

从两个电子罗盘的数据手册上看,两个模块在寄存器上还是有差异的,具体的话不多说,看下图:

从模块的芯片丝印来看,两者的丝印是不同的。

HMC5883L的丝印为L883,QMC5883L的丝印正常为HA5883,大家一定要记住!

首先,HMC5883L是进口的芯片,QMC5883L为国产仿制芯片,在价格上差异就不小,其次,根据研发经验来看,国产QMC5883L芯片在稳定性方面就差不少。所以在购买的时候大家要记住差异。

好啦,感谢小伙伴的查阅,在技术方面,有兴趣的小伙伴可以一起探讨一下。