极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 34193|回复: 8

HMC5883L转换方向角与简易校准方法

[复制链接]
发表于 2015-2-8 23:01:35 | 显示全部楼层 |阅读模式
本帖最后由 do335maomao 于 2015-2-9 11:24 编辑




研究了一晚上稍微有点成果分享下

HMC5883L使用i2c接口,接线很容易

以Arduino Uno为例:
SDA to A4
SCL to A5
Vcc to 3.3V
GND to GND

基本原理很简单:
方向角其实就是X轴和Y轴读数的反正切
而校准其实就是要排除环境中的磁场对地磁场的干扰
另外别忘了当地的磁偏角

如下代码没有使用专门的传感器库
上电后先进行20秒校准,请把传感器任意乱转,各个方向都要转到
然后就会显示校准值,然后持续显示初始值和方向角
不知道怎么在ide里面用中文写注释,所以就保留英文了

个人测试下来和手机上的指南针相差不超过5度,更精细的校准待研究

刚刚接触Arduino,望高手指教




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

  2. #define address 0x1E //001 1110b(0x3C>>1), I2C 7bit address of HMC5883
  3. #define MagnetcDeclination 4.43 //Shanghai
  4. #define CalThreshold 0

  5. int offsetX,offsetY,offsetZ;

  6. void setup()
  7. {
  8.   //Initialize Serial and I2C communications
  9.   Serial.begin(9600);
  10.   Wire.begin();

  11.   //Put the HMC5883 IC into the correct operating mode
  12.   Wire.beginTransmission(address); //open communication with HMC5883r
  13.   Wire.write(0x00); //select configuration register A
  14.   Wire.write(0x70); //0111 0000b configuration
  15.   Wire.endTransmission();
  16.   
  17.   Wire.beginTransmission(address);
  18.   Wire.write(0x02); //select mode register
  19.   Wire.write(0x00); //set continuous measurement mode:0x00,single-measurement mode:0x01
  20.   Wire.endTransmission();
  21.   
  22.   calibrateMag();
  23. }
  24. void loop()
  25. {
  26.   int x,y,z; //triple axis data
  27.   getRawData(&x,&y,&z);
  28.   
  29.   //Print out values of each axis
  30.   Serial.print("x: ");
  31.   Serial.print(x);
  32.   Serial.print("  y: ");
  33.   Serial.print(y);
  34.   Serial.print("  z: ");
  35.   Serial.print(z);
  36.   Serial.print(" angle(x,y): ");
  37.   Serial.println(calculateHeading(&x,&y,&z));

  38.   delay(250);
  39. }

  40. void getRawData(int* x ,int* y,int* z)
  41. {
  42.   //Tell the HMC5883L where to begin reading data
  43.   Wire.beginTransmission(address);
  44.   Wire.write(0x03); //select register 3, X MSB register
  45.   Wire.endTransmission();
  46.   //Read data from each axis, 2 registers per axis
  47.   Wire.requestFrom(address, 6);
  48.   if(6<=Wire.available()){
  49.     *x = Wire.read()<<8; //X msb
  50.     *x |= Wire.read(); //X lsb
  51.     *z = Wire.read()<<8; //Z msb
  52.     *z |= Wire.read(); //Z lsb
  53.     *y = Wire.read()<<8; //Y msb
  54.     *y |= Wire.read(); //Y lsb
  55.   }
  56. }

  57. int calculateHeading(int* x ,int* y,int* z)
  58. {
  59.   float headingRadians = atan2((double)((*y)-offsetY),(double)((*x)-offsetX));
  60.   // Correct for when signs are reversed.
  61.   if(headingRadians < 0)
  62.     headingRadians += 2*PI;
  63.    
  64.   int headingDegrees = headingRadians * 180/M_PI;
  65.   headingDegrees += MagnetcDeclination; //the magnetc-declination angle
  66.   
  67.   // Check for wrap due to addition of declination.
  68.   if(headingDegrees > 360)
  69.     headingDegrees -= 360;
  70.   
  71.   return headingDegrees;
  72. }

  73. void calibrateMag()
  74. {
  75.   int x,y,z; //triple axis data
  76.   int xMax, xMin, yMax, yMin, zMax, zMin;
  77.   //initialize the variables
  78.   getRawData(&x,&y,&z);  
  79.   xMax=xMin=x;
  80.   yMax=yMin=y;
  81.   zMax=zMin=z;
  82.   offsetX = offsetY = offsetZ = 0;
  83.   
  84.   Serial.println("Starting Calibration......");
  85.   Serial.println("Please turn your device around in 20 seconds");
  86.   
  87.   for(int i=0;i<200;i++)
  88.   {
  89.     getRawData(&x,&y,&z);
  90.     //get Max and Min
  91.     // this routine will capture the max and min values of the mag X, Y, and Z data while the
  92.     // compass is being rotated 360 degrees through the level plane and the upright plane.
  93.     // i.e. horizontal and vertical circles.
  94.     // This function should be invoked while making continuous measurements on the magnetometers
  95.     if (x > xMax)
  96.       xMax = x;
  97.     if (x < xMin )
  98.       xMin = x;
  99.     if(y > yMax )
  100.       yMax = y;
  101.     if(y < yMin )
  102.       yMin = y;
  103.     if(z > zMax )
  104.       zMax = z;
  105.     if(z < zMin )
  106.       zMin = z;
  107.       
  108.     delay(100);
  109.    
  110.     if(i%10 == 0)
  111.     {
  112.       Serial.print(xMax);
  113.       Serial.print(" ");
  114.       Serial.println(xMin);
  115.     }
  116.   }
  117.   //compute offsets
  118.   if(abs(xMax - xMin) > CalThreshold )
  119.     offsetX = (xMax + xMin)/2;
  120.   if(abs(yMax - yMin) > CalThreshold )
  121.     offsetY = (yMax + yMin)/2;
  122.   if(abs(zMax - zMin) > CalThreshold )
  123.     offsetZ = (zMax +zMin)/2;
  124.    
  125.   Serial.print("offsetX:");
  126.   Serial.print("");
  127.   Serial.print(offsetX);
  128.   Serial.print(" offsetY:");
  129.   Serial.print("");
  130.   Serial.print(offsetY);
  131.   Serial.print(" offsetZ:");
  132.   Serial.print("");
  133.   Serial.println(offsetZ);
  134.   
  135.   delay(5000);  
  136. }


复制代码


把冗长的数据手册读完了,有人想看的话,可以把自测试模式,空闲模式等的使用方法也写一下

参考资料:
https://www.sparkfun.com/tutorials/301

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2015-2-9 09:02:34 | 显示全部楼层
正在研究这个,谢谢楼主分享!
回复 支持 反对

使用道具 举报

发表于 2015-2-27 14:48:06 | 显示全部楼层
我用的GY86模块,电子罗盘也是HMC5883L,一直显示I2C通讯失败,但是MPU6050这些I2C都没问题,楼主能点拨一下吗?谢谢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-28 14:59:13 | 显示全部楼层
kevinfrankchen 发表于 2015-2-27 14:48
我用的GY86模块,电子罗盘也是HMC5883L,一直显示I2C通讯失败,但是MPU6050这些I2C都没问题,楼主能点拨一下 ...


gy86上的hmc5883是连在mpu6050的辅助i2c口上的,需要设置mpu6050才能使用罗盘
回复 支持 反对

使用道具 举报

发表于 2015-2-28 15:40:59 | 显示全部楼层
do335maomao 发表于 2015-2-28 14:59
gy86上的hmc5883是连在mpu6050的辅助i2c口上的,需要设置mpu6050才能使用罗盘

你好,那你有相关的历程吗?我还以为那个模块坏了,谢谢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-2-28 16:41:11 | 显示全部楼层
kevinfrankchen 发表于 2015-2-28 15:40
你好,那你有相关的历程吗?我还以为那个模块坏了,谢谢

这个我具体也只是看过数据手册,建议你也看一下
回复 支持 反对

使用道具 举报

发表于 2015-5-29 16:02:19 | 显示全部楼层
楼主你好,我看到你的calibrateMag()部分代码的时候,看到只打印出xMax和xMin值,请问校准只需要X轴获取最大和最小即可么?

小白不懂,万分感谢
回复 支持 反对

使用道具 举报

发表于 2015-11-26 19:02:06 | 显示全部楼层

请问M_PI是一个什么数??我一直没找到

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

发表于 2016-4-22 20:14:05 | 显示全部楼层
LZ竟然没用HMC5883L库!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-15 02:26 , Processed in 0.054013 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表