HMC5883L三轴陀螺仪(模拟IIC读取和传感器校准)
2015-11-24 20:46
239 查看
HMC5883L是一个三轴陀螺仪,能实现待测点的地磁场方向。
我在试验中只用到了水平方向的磁场方向。跟据地磁场的知识可知,在北半球,磁场方向指向地面。并且还有地理北极和地磁北极的磁偏角是11度。
使用磁传感器应注意以下几点:
1.读取到的传感器数据是当地磁场在空间x,y,z三个方向上的分量。
2.在水平方向,地磁偏角的计算公式是:磁偏角:Curent_Angle = (atan2(Y,X) * (180 / 3.14159265) + 180);
3.传感器应该以软件的方式校准。
好了,贴上代码:
好了,以上就是我使用过程中的一些总结,不足之处还请各位指出。
我在试验中只用到了水平方向的磁场方向。跟据地磁场的知识可知,在北半球,磁场方向指向地面。并且还有地理北极和地磁北极的磁偏角是11度。
使用磁传感器应注意以下几点:
1.读取到的传感器数据是当地磁场在空间x,y,z三个方向上的分量。
2.在水平方向,地磁偏角的计算公式是:磁偏角:Curent_Angle = (atan2(Y,X) * (180 / 3.14159265) + 180);
3.传感器应该以软件的方式校准。
好了,贴上代码:
static void i2c_Delay(void) { uint8_t i; /* 下面的时间是通过安富莱AX-Pro逻辑分析仪测试得到的。 CPU主频72MHz时,在内部Flash运行, MDK工程不优化 循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us IAR工程编译效率高,不能设置为7 */ for (i = 0; i < 10; i++); } void i2c_Start(void) { /* 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */ I2C_SDA_1(); i2c_Delay(); I2C_SCL_1(); i2c_Delay(); I2C_SDA_0(); i2c_Delay(); I2C_SCL_0(); i2c_Delay(); } void i2c_Stop(void) { /* 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号 */ I2C_SDA_0(); i2c_Delay(); I2C_SCL_1(); i2c_Delay(); I2C_SDA_1(); } void i2c_SendByte(uint8_t _ucByte) { uint8_t i; /* 先发送字节的高位bit7 */ for (i = 0; i < 8; i++) { if (_ucByte & 0x80) { I2C_SDA_1(); } else { I2C_SDA_0(); } i2c_Delay(); I2C_SCL_1(); i2c_Delay(); I2C_SCL_0(); if (i == 7) { I2C_SDA_1(); // 释放总线 } _ucByte <<= 1; /* 左移一个bit */ i2c_Delay(); } } uint8_t i2c_ReadByte(void) { uint8_t i; uint8_t value; I2C_SDA_1(); /* 读到第1个bit为数据的bit7 */ value = 0; for (i = 0; i < 8; i++) { value <<= 1; I2C_SCL_1(); i2c_Delay(); if (I2C_SDA_READ()) { value++; } I2C_SCL_0(); i2c_Delay(); } return value; } uint8_t i2c_WaitAck(void) { uint8_t re; I2C_SDA_1(); /* CPU释放SDA总线 */ i2c_Delay(); I2C_SCL_1(); /* CPU驱动SCL = 1, 此时器件会返回ACK应答 */ i2c_Delay(); if (I2C_SDA_READ()) /* CPU读取SDA口线状态 */ { re = 1; } else { re = 0; } I2C_SCL_0(); i2c_Delay(); return re; } void i2c_Ack(void) { I2C_SDA_0(); /* CPU驱动SDA = 0 */ i2c_Delay(); I2C_SCL_1(); /* CPU产生1个时钟 */ i2c_Delay(); I2C_SCL_0(); i2c_Delay(); I2C_SDA_1(); /* CPU释放SDA总线 */ } void i2c_NAck(void) { I2C_SDA_1(); /* CPU驱动SDA = 1 */ i2c_Delay(); I2C_SCL_1(); /* CPU产生1个时钟 */ i2c_Delay(); I2C_SCL_0(); i2c_Delay(); } void HMC5883L_Init() { i2c_CheckDevice(HMC5883L_Write_Address); i2c_Start(); i2c_SendByte(HMC5883L_Write_Address | I2C_WR); i2c_WaitAck(); i2c_SendByte(0x00); i2c_WaitAck(); i2c_SendByte(0x70); i2c_WaitAck(); i2c_SendByte(0x01); i2c_WaitAck(); i2c_SendByte(0xe0); i2c_WaitAck(); i2c_SendByte(0x02); i2c_WaitAck(); i2c_SendByte(0x01); i2c_Stop(); } float Get_Current_Angle() { u8 i; u8 a[6]; float Curent_Angle; HMC5883L_Init(); i2c_Start(); i2c_SendByte(HMC5883L_Write_Address | I2C_WR); i2c_WaitAck(); i2c_SendByte(0x03); i2c_WaitAck(); i2c_Start(); i2c_SendByte(HMC5883L_Write_Address | I2C_RD); i2c_WaitAck(); for(i=0;i<6;i++) { a[i] = i2c_ReadByte(); if(i==5) { i2c_NAck(); } else { i2c_Ack(); } } i2c_Stop(); x=a[0]; x=x<<8; x=x|a[1]; y=a[2]; y=y<<8; y=y|a[3]; z=a[4]; z=z<<8; z=z|a[5]; if(x>32768) { x = -(0xFFFF - x + 1); } if(y>32768) { y = -(0xFFFF - y + 1); } if(z>32768) { z = -(0xFFFF - z + 1); } X = (s16)x; //x分量 Y = (s16)y; //y分量 Z = (s16)z; //z分量 Curent_Angle = (atan2(Y,X) * (180 / 3.14159265) + 180); //实际水平角度 return Curent_Angle; }
另外一个重要的事是校准。在网上找了很多资料,关于怎么校准,有些资料不公开,所以贴上一个百度文库网址,自己没有下载点券,囧。。。。
http://wenku.baidu.com/link?url=EqAo3QFYDZsgfzlAKcm9FTKAc-42zxWw0iUIll8Wde79OLLJzq_GvSUubk2X30zhBM-4_X8U4xLlhxce8W-28T8RIC28cIa8A9nzbUEHzlu
这上面说明了校准的具体操作和代码。
下面贴上我写的:<pre name="code" class="html">void calibrate() { float xMax, xMin, yMax, yMin, zMax, zMin; xMax=xMin=x; yMax=yMin=y; zMax=zMin=z; float offsetX = 0; float offsetY = 0; float offsetZ = 0; for(int i=0;i<200;i++) { if (x > xMax) xMax = x; if (x < xMin ) xMin = x; if(y > yMax ) yMax = y; if(y < yMin ) yMin = y; if(z > zMax ) zMax = z; if(z < zMin ) zMin = z; delay(100); } if(abs(xMax - xMin) > 0 ) offsetX = (xMax + xMin)/2; if(abs(yMax - yMin) > 0 ) offsetY = (yMax + yMin)/2; if(abs(zMax - zMin) > 0 ) offsetZ = (zMax +zMin)/2; }
好了,以上就是我使用过程中的一些总结,不足之处还请各位指出。
相关文章推荐
- Java集合概述
- java集合类
- 图解TCP/IP读书笔记(二)
- CentOS Linux 上安装svn服务器
- [2561]:第二小整数
- BZOJ 2724: [Violet 6]蒲公英
- CF 431C k-Tree
- NYOJ 1148-图形寻点
- POJ 3067 Japan 【树状数组 向下更新 向上求和】
- 28.UITableView表视图第三章(移动和编辑删除和添加)
- codeforces 492B
- 解决spring使用动态代理类型转换失败的问题--java.lang.ClassCastException: com.sun.proxy.$Proxy$ cannot be cast to ...
- 图遍历算法实现
- mac compile php for pdo_pgsql
- 折线分割平面
- K60 FlexBus总线液晶调试 SSD1289(ID8989)液晶 补充:FlexBus总线驱动成功
- 贪心算法_乘船问题
- 加载网络图片的框架总结
- ios 枚举 位移操作
- 《leetCode》:Search in Rotated Sorted Array