[求助] 基于mpu6050加速度传感器和51单片机的无线鼠标设计,有关加速度传感器的数据处理

shanghen   2015-5-18 12:40 楼主
      各位大牛,有关于基于mpu6050加速度传感器和51单片机的无线鼠标设计,有关加速度传感器的数据处理部分,就是mpu6050输出的部分是3个轴的加速度和三个角加速度,现在不管角加速度嘛,就是如何将程序中的三个加速度进行数据处理,最后使其输出是从当前时刻到某时刻总共走的位移?求指导!加速度传感器的程序如下。



  1. //****************************************
  2. // Update to MPU6050 by shinetop
  3. // MCU: STC89C52
  4. // 2012.3.1
  5. // 功能: 显示加速度计和陀螺仪的10位原始数据
  6. //****************************************
  7. // GY-52 MPU3050 IIC测试程序
  8. // 使用单片机STC89C51
  9. // 晶振:11.0592M
  10. // 显示:LCD1602
  11. // 编译环境 Keil uVision2
  12. // 参考宏晶网站24c04通信程序
  13. // 时间:2011年9月1日
  14. // QQ:531389319
  15. //****************************************
  16. #include <reg52.H>       
  17.    //Keil library  
  18. #include <stdio.h>   //Keil library       
  19. #include <INTRINS.H>
  20. typedef unsigned char  uchar;
  21. typedef unsigned short ushort;
  22. typedef unsigned int   uint;
  23. //****************************************
  24. // 定义51单片机端口
  25. //****************************************
  26. #define DataPort P0                //LCD1602数据端口
  27. sbit    SCL=P1^0;                        //IIC时钟引脚定义
  28. sbit    SDA=P1^1;                        //IIC数据引脚定义
  29. sbit    LCM_RS=P3^5;                //LCD1602命令端口               
  30. //sbit    LCM_RW=P3^6;                //LCD1602命令端口               
  31. sbit    LCM_EN=P3^4;                //LCD1602命令端口
  32. sbit    WELA=P2^7;
  33. sbit    dula=P2^6;
  34. //****************************************
  35. // 定义MPU6050内部地址
  36. //****************************************
  37. #define        SMPLRT_DIV                0x19        //陀螺仪采样率,典型值:0x07(125Hz)
  38. #define        CONFIG                        0x1A        //低通滤波频率,典型值:0x06(5Hz)
  39. #define        GYRO_CONFIG                0x1B        //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
  40. #define        ACCEL_CONFIG        0x1C        //加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)
  41. #define        ACCEL_XOUT_H        0x3B
  42. #define        ACCEL_XOUT_L        0x3C
  43. #define        ACCEL_YOUT_H        0x3D
  44. #define        ACCEL_YOUT_L        0x3E
  45. #define        ACCEL_ZOUT_H        0x3F
  46. #define        ACCEL_ZOUT_L        0x40
  47. #define        TEMP_OUT_H                0x41
  48. #define        TEMP_OUT_L                0x42
  49. #define        GYRO_XOUT_H                0x43
  50. #define        GYRO_XOUT_L                0x44       
  51. #define        GYRO_YOUT_H                0x45
  52. #define        GYRO_YOUT_L                0x46
  53. #define        GYRO_ZOUT_H                0x47
  54. #define        GYRO_ZOUT_L                0x48
  55. #define        PWR_MGMT_1                0x6B        //电源管理,典型值:0x00(正常启用)
  56. #define        WHO_AM_I                        0x75        //IIC地址寄存器(默认数值0x68,只读)
  57. #define        SlaveAddress        0xD0        //IIC写入时的地址字节数据,+1为读取
  58. //****************************************
  59. //定义类型及变量
  60. //****************************************
  61. uchar dis[4];                                                        //显示数字(-511至512)的字符数组
  62. int        dis_data;                                                //变量
  63. //int        Temperature,Temp_h,Temp_l;        //温度及高低位数据
  64. //****************************************
  65. //函数声明
  66. //****************************************
  67. void  delay(unsigned int k);                                                                                //延时
  68. //LCD相关函数
  69. void  InitLcd();                                                                                                                //初始化lcd1602
  70. void  lcd_printf(uchar *s,int temp_data);
  71. void  WriteDataLCM(uchar dataW);                                                                        //LCD数据
  72. void  WriteCommandLCM(uchar CMD);                                //LCD指令
  73. void  DisplayOneChar(uchar X,uchar Y,uchar DData);                        //显示一个字符
  74. void  DisplayListChar(uchar X,uchar Y,uchar *DData,L);        //显示字符串
  75. //MPU6050操作函数
  76. void  InitMPU6050();                                                                                                        //初始化MPU6050
  77. void  Delay5us();
  78. void  I2C_Start();
  79. void  I2C_Stop();
  80. void  I2C_SendACK(bit ack);
  81. bit   I2C_RecvACK();
  82. void  I2C_SendByte(uchar dat);
  83. uchar I2C_RecvByte();
  84. void  I2C_ReadPage();
  85. void  I2C_WritePage();
  86. void  display_ACCEL_x();
  87. void  display_ACCEL_y();
  88. void  display_ACCEL_z();
  89. uchar Single_ReadI2C(uchar REG_Address);                                                //读取I2C数据
  90. void  Single_WriteI2C(uchar REG_Address,uchar REG_data);        //向I2C写入数据
  91. //****************************************
  92. //整数转字符串
  93. //****************************************
  94. void lcd_printf(uchar *s,int temp_data)
  95. {
  96.         if(temp_data<0)
  97.         {
  98.                 temp_data=-temp_data;
  99.                 *s='-';
  100.         }
  101.         else *s=' ';
  102.         *++s =temp_data/100+0x30;
  103.         temp_data=temp_data%100;     //取余运算
  104.         *++s =temp_data/10+0x30;
  105.         temp_data=temp_data%10;      //取余运算
  106.         *++s =temp_data+0x30;        
  107. }
  108. //****************************************
  109. //延时
  110. //****************************************
  111. void delay(unsigned int k)       
  112. {                                               
  113.         unsigned int i,j;                               
  114.         for(i=0;i<k;i++)
  115.         {                       
  116.                 for(j=0;j<121;j++);
  117.         }                                               
  118. }
  119. //****************************************
  120. //LCD1602初始化
  121. //****************************************
  122. void InitLcd()                               
  123. {       
  124.     WELA=0;
  125.     dula=0;
  126.     LCM_EN=0;               
  127.         WriteCommandLCM(0x38);       
  128.         WriteCommandLCM(0x08);       
  129.         WriteCommandLCM(0x01);       
  130.         WriteCommandLCM(0x06);       
  131.         WriteCommandLCM(0x0c);
  132.         DisplayOneChar(0,0,'A');
  133.         DisplayOneChar(0,1,'G');
  134. }                       
  135. //****************************************
  136. //LCD1602写允许
  137. //****************************************
  138. /*void WaitForEnable(void)       
  139. {                                       
  140.         DataPort=0xff;               
  141.         LCM_RS=0;LCM_RW=1;_nop_();
  142.         LCM_EN=1;_nop_();_nop_();
  143.         while(DataPort&0x80);       
  144.         LCM_EN=0;                               
  145. }*/                                       
  146. //****************************************
  147. //LCD1602写入命令
  148. //****************************************
  149. void WriteCommandLCM(uchar CMD)
  150. {                                       
  151.         //if(Attribc)WaitForEnable();       
  152.         LCM_RS=0;//LCM_RW=0;
  153.         DataPort=CMD;
  154.     delay(5);       
  155.         LCM_EN=1;
  156.     delay(5);
  157.     LCM_EN=0;
  158. }                                       
  159. //****************************************
  160. //LCD1602写入数据
  161. //****************************************
  162. void WriteDataLCM(uchar dataW)
  163. {                                       
  164.         //WaitForEnable();               
  165.         LCM_RS=1;
  166.         DataPort=dataW;
  167.     delay(5);       
  168.         LCM_EN=1;
  169.     delay(5);   
  170.     LCM_EN=0;
  171. }               
  172. //****************************************
  173. //LCD1602写入一个字符
  174. //****************************************
  175. void DisplayOneChar(uchar X,uchar Y,uchar DData)
  176. {                                               
  177.         Y&=1;                                               
  178.         X&=15;                                               
  179.         if(Y)X|=0x40;                                       
  180.         X|=0x80;                       
  181.         WriteCommandLCM(X);               
  182.         WriteDataLCM(DData);               
  183. }                                               
  184. //****************************************
  185. //LCD1602显示字符串
  186. //****************************************
  187. void DisplayListChar(uchar X,uchar Y,uchar *DData,L)
  188. {
  189.         uchar ListLength=0;
  190.         Y&=0x1;               
  191.         X&=0xF;               
  192.         while(L--)            
  193.         {                       
  194.                 DisplayOneChar(X,Y,DData[ListLength]);
  195.                 ListLength++;  
  196.                 X++;                        
  197.         }   
  198. }
  199. //**************************************
  200. //延时5微秒(STC90C52RC@12M)
  201. //不同的工作环境,需要调整此函数
  202. //当改用1T的MCU时,请调整此延时函数
  203. //**************************************
  204. void Delay5us()
  205. {
  206.         _nop_();_nop_();_nop_();_nop_();
  207.         _nop_();_nop_();_nop_();_nop_();
  208.         _nop_();_nop_();_nop_();_nop_();
  209.         _nop_();_nop_();_nop_();_nop_();
  210.         _nop_();_nop_();_nop_();_nop_();
  211.         _nop_();_nop_();_nop_();_nop_();
  212. }
  213. //**************************************
  214. //I2C起始信号
  215. //**************************************
  216. void I2C_Start()
  217. {
  218.     SDA = 1;                    //拉高数据线
  219.     SCL = 1;                    //拉高时钟线
  220.     Delay5us();                 //延时
  221.     SDA = 0;                    //产生下降沿
  222.     Delay5us();                 //延时
  223.     SCL = 0;                    //拉低时钟线
  224. }
  225. //**************************************
  226. //I2C停止信号
  227. //**************************************
  228. void I2C_Stop()
  229. {
  230.     SDA = 0;                    //拉低数据线
  231.     SCL = 1;                    //拉高时钟线
  232.     Delay5us();                 //延时
  233.     SDA = 1;                    //产生上升沿
  234.     Delay5us();                 //延时
  235. }
  236. //**************************************
  237. //I2C发送应答信号
  238. //入口参数:ack (0:ACK 1:NAK)
  239. //**************************************
  240. void I2C_SendACK(bit ack)
  241. {
  242.     SDA = ack;                  //写应答信号
  243.     SCL = 1;                    //拉高时钟线
  244.     Delay5us();                 //延时
  245.     SCL = 0;                    //拉低时钟线
  246.     Delay5us();                 //延时
  247. }
  248. //**************************************
  249. //I2C接收应答信号
  250. //**************************************
  251. bit I2C_RecvACK()
  252. {
  253.     SCL = 1;                    //拉高时钟线
  254.     Delay5us();                 //延时
  255.     CY = SDA;                   //读应答信号
  256.     SCL = 0;                    //拉低时钟线
  257.     Delay5us();                 //延时
  258.     return CY;
  259. }
  260. //**************************************
  261. //向I2C总线发送一个字节数据
  262. //**************************************
  263. void I2C_SendByte(uchar dat)
  264. {
  265.     uchar i;
  266.     for (i=0; i<8; i++)         //8位计数器
  267.     {
  268.         dat <<= 1;              //移出数据的最高位
  269.         SDA = CY;               //送数据口
  270.         SCL = 1;                //拉高时钟线
  271.         Delay5us();             //延时
  272.         SCL = 0;                //拉低时钟线
  273.         Delay5us();             //延时
  274.     }
  275.     I2C_RecvACK();
  276. }
  277. //**************************************
  278. //从I2C总线接收一个字节数据
  279. //**************************************
  280. uchar I2C_RecvByte()
  281. {
  282.     uchar i;
  283.     uchar dat = 0;
  284.     SDA = 1;                    //使能内部上拉,准备读取数据,
  285.     for (i=0; i<8; i++)         //8位计数器
  286.     {
  287.         dat <<= 1;
  288.         SCL = 1;                //拉高时钟线
  289.         Delay5us();             //延时
  290.         dat |= SDA;             //读数据               
  291.         SCL = 0;                //拉低时钟线
  292.         Delay5us();             //延时
  293.     }
  294.     return dat;
  295. }
  296. //**************************************
  297. //向I2C设备写入一个字节数据
  298. //**************************************
  299. void Single_WriteI2C(uchar REG_Address,uchar REG_data)
  300. {
  301.     I2C_Start();                  //起始信号
  302.     I2C_SendByte(SlaveAddress);   //发送设备地址+写信号
  303.     I2C_SendByte(REG_Address);    //内部寄存器地址,
  304.     I2C_SendByte(REG_data);       //内部寄存器数据,
  305.     I2C_Stop();                   //发送停止信号
  306. }
  307. //**************************************
  308. //从I2C设备读取一个字节数据
  309. //**************************************
  310. uchar Single_ReadI2C(uchar REG_Address)
  311. {
  312.         uchar REG_data;
  313.         I2C_Start();                   //起始信号
  314.         I2C_SendByte(SlaveAddress);    //发送设备地址+写信号
  315.         I2C_SendByte(REG_Address);     //发送存储单元地址,从0开始       
  316.         I2C_Start();                   //起始信号
  317.         I2C_SendByte(SlaveAddress+1);  //发送设备地址+读信号
  318.         REG_data=I2C_RecvByte();       //读出寄存器数据
  319.         I2C_SendACK(1);                //接收应答信号
  320.         I2C_Stop();                    //停止信号
  321.         return REG_data;
  322. }
  323. //**************************************
  324. //初始化MPU6050
  325. //**************************************
  326. void InitMPU6050()
  327. {
  328.         Single_WriteI2C(PWR_MGMT_1, 0x00);        //解除休眠状态
  329.         Single_WriteI2C(SMPLRT_DIV, 0x07);
  330.         Single_WriteI2C(CONFIG, 0x06);
  331.         Single_WriteI2C(GYRO_CONFIG, 0x18);
  332.         Single_WriteI2C(ACCEL_CONFIG, 0x01);
  333. }
  334. //**************************************
  335. //合成数据
  336. //**************************************
  337. int GetData(uchar REG_Address)
  338. {
  339.         char H,L;
  340.         H=Single_ReadI2C(REG_Address);
  341.         L=Single_ReadI2C(REG_Address+1);
  342.         return (H<<8)+L;   //合成数据
  343. }
  344. //**************************************
  345. //在1602上显示10位数据
  346. //**************************************
  347. void Display10BitData(int value,uchar x,uchar y)
  348. {
  349.         value/=64;                                                        //转换为10位数据
  350.         lcd_printf(dis, value);                        //转换数据显示
  351.         DisplayListChar(x,y,dis,4);        //启始列,行,显示数组,显示长度
  352. }
  353. //**************************************
  354. //显示温度
  355. //**************************************
  356. //void display_temp()
  357. //{
  358. //        Temp_h=Single_ReadI2C(TEMP_OUT_H); //读取温度
  359. //        Temp_l=Single_ReadI2C(TEMP_OUT_L); //读取温度
  360. //        Temperature=Temp_h<<8|Temp_l;     //合成温度
  361. //        Temperature = 35+ ((double) (Temperature + 13200)) / 280; // 计算出温度
  362. //        lcd_printf(dis,Temperature);     //转换数据显示
  363. //        DisplayListChar(11,1,dis,4);     //启始列,行,显示数组,显示位数
  364. //}
  365. //*********************************************************
  366. //主程序
  367. //*********************************************************
  368. void main()
  369. {
  370.         delay(500);                //上电延时               
  371.         InitLcd();                //液晶初始化
  372.         InitMPU6050();        //初始化MPU6050
  373.         delay(150);
  374.     P0=0XFF;
  375.         delay(50);
  376.         WELA=1;
  377.         delay(50);
  378.         WELA=0;

  379.         while(1)
  380.         {
  381.                 Display10BitData(GetData(ACCEL_XOUT_H),2,0);        //显示X轴加速度
  382.                 Display10BitData(GetData(ACCEL_YOUT_H),7,0);        //显示Y轴加速度
  383.                 Display10BitData(GetData(ACCEL_ZOUT_H),12,0);        //显示Z轴加速度
  384.                 Display10BitData(GetData(GYRO_XOUT_H),2,1);        //显示X轴角速度
  385.                 Display10BitData(GetData(GYRO_YOUT_H),7,1);        //显示Y轴角速度
  386.                 Display10BitData(GetData(GYRO_ZOUT_H),12,1);        //显示Z轴角速度
  387.                 delay(500);
  388.         }
  389. }


    jiasudu - 副本.txt (2015-5-18 12:39 上传)

    11.5 KB, 下载次数: 92

    加速度传感器的程序

回复评论 (11)

2推荐 littleshrimp 

这是一个比较复杂的算法,可以参考
http://www.doc88.com/p-9069095363808.html


等盲导系统
虾扯蛋,蛋扯虾,虾扯蛋扯虾
点赞  2015-5-18 15:17
51去滤波融合解算,是不是太摩托骡拉了
So TM what......?
点赞  2015-5-18 15:16
1、原始数据虑个波
2、把极限时间内的两个数据融合一下
3、用xx法,谈论得比较多的是四元数,把姿态算出来
So TM what......?
点赞  2015-5-18 15:22
感觉mpu6050不太适合做惯性导航,精度太低,给你看看我用mpu6050做的惯性导航视频http://v.youku.com/v_show/id_XOTYxMDk0NTA4.html?from=y1.7-1.2
QQ:252669569
点赞  2015-5-21 23:05


但是用作鼠标控制的话,认为控制光标位置的话,对精度要求并不是很高,就是后续算法不知道怎么办,求指导。你这个做惯性导航的视频里面只有速度信息,没得位移的嘛 ,速度是靠积分来的还是怎么来的?
点赞  2015-5-26 12:35


但是用作鼠标控制的话,认为控制光标位置的话,对精度要求并不是很高,就是后续算法不知道怎么办,求指导。你这个做惯性导航的视频里面只有速度信息,没得位移的嘛 ,速度是靠积分来的还是怎么来的?
点赞  2015-5-26 12:36
引用: shanghen 发表于 2015-5-26 12:35
但是用作鼠标控制的话,认为控制光标位置的话,对精度要求并不是很高,就是后续算法不知道怎么办,求指导。你这个做惯性导航的视频里面只有速度信息,没得位移的嘛 ,速度是靠积分来的还是怎么来的?

速度是靠加速度积分来的
QQ:252669569
点赞  2015-5-26 16:43
引用: lb8820265 发表于 2015-5-26 16:43
速度是靠加速度积分来的

能不能看看你的代码 我的QQ 67582379@qq.com
点赞  2015-6-19 17:51
引用: lb8820265 发表于 2015-5-26 16:43
速度是靠加速度积分来的

能贴出相关代码吗?我目前也在做一个利用加速度传感器数据控制鼠标的小项目  我也看了你发的视频 感觉还是有点不稳定  鼠标存在反向问题
点赞  2016-3-15 15:05
引用: yqdby1992 发表于 2016-3-15 15:05
能贴出相关代码吗?我目前也在做一个利用加速度传感器数据控制鼠标的小项目  我也看了你发的视频 感觉还 ...

代码现在找不到了,不过我用的代码相当的简单,就是用的加速度减去重力加速度的值然后积分,然后弄很大的死区,所以代码并没有什么价值,如果可以建议去研究下Pixhawk这种飞控中的惯性导航代码。
QQ:252669569
点赞  2016-3-16 00:11
加速度积分与计时器计算位移啊
点赞  2016-8-15 17:01
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复