HMC5883L电子罗盘原理及应用,全网最详细~

·寄存器配置部分

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_MASK      0x03
#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_5    0x04
#define HMC5883_REG_CRA_DO_Hz_3      0x08
#define HMC5883_REG_CRA_DO_Hz_7_5    0x0C
#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_MASK      0x60
#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_G1370    0x00
#define HMC5883_REG_GN_1_30_G1090    0x20 // 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_CON      0x00    
#define HMC5883_REG_MODE_MR_SIG      0x01 // default   
#define HMC5883_REG_MODE_MR_IDLE1    0x02    
#define HMC5883_REG_MODE_MR_IDLE2    0x03    

/* 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 <= 67) {
        obj.direction = DIRECTION_NE;
    } else if (obj.xz_angle_val >= 68  && obj.xz_angle_val <= 111) {
        obj.direction = DIRECTION_E;
    } else if (obj.xz_angle_val >= 112 && obj.xz_angle_val <= 157) {
        obj.direction = DIRECTION_SE;
    } else if (obj.xz_angle_val >= 158 && obj.xz_angle_val <= 201) {
        obj.direction = DIRECTION_S;
    } else if (obj.xz_angle_val >= 202 && obj.xz_angle_val <= 247) {
        obj.direction = DIRECTION_SW;
    } else if (obj.xz_angle_val >= 248 && obj.xz_angle_val <= 291) {
        obj.direction = DIRECTION_W;
    } else if (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芯片在稳定性方面就差不少。所以在购买的时候大家要记住差异。

 

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

物联沃分享整理
物联沃-IOTWORD物联网 » HMC5883L电子罗盘原理及应用,全网最详细~

发表评论