资源预览内容
第1页 / 共11页
第2页 / 共11页
第3页 / 共11页
第4页 / 共11页
第5页 / 共11页
第6页 / 共11页
第7页 / 共11页
第8页 / 共11页
第9页 / 共11页
第10页 / 共11页
亲,该文档总共11页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
MPU6050 数据采集传输与可视化数据采集传输与可视化 最近在研究体感游戏,到目前为止实现了基于 51 单片机的 MPU6050 数据采集、利用蓝牙模块将数据传输到上 位机, 并利用 C#自制串口数据高速采集软件, 并且将数据通过自制的折线图绘制模块可视化地展示出来等功能。 本文将主要对实现这意见单系统中遇到的问题做一个小结其中包括: 1、基于 51 的 MPU6050 模块通信简介(入门级) 2、陀螺仪数据采集与传输及帧格式介绍(小技巧) 3、基于 C#的串口接收函数(C#基本知识) 4、多线程数据池解决高速串口实时性问题(难点) 5、折线图可视化模块(程序员基本功) 关键词:MPU6050 蓝牙 C#串口 多线程 高速串口 折线图绘制 1、基于、基于 51 的的 MPU6050 模块通信简介(入门级)模块通信简介(入门级) 因为是入门级, 就先最简单的介绍如何利用 51 从 MPU6050 中读取数据吧 (对于想知道卡尔曼滤波、 俯角仰角、 距离测量、摔倒检测、记步等算法的可能要在接下来介绍)。既然要和 MPU6050 通信,那么必不可少的是阅读 芯片手册,如果您觉得亲自去看又长又多而且都是英文的手册很费时,不仿看看我找的简要版: MPU-60X0 是全球首例 9 轴运动处理器。它集成了 3 轴 MEMS 陀螺仪,3 轴 MEMS 加速计,以及 1 个可扩展 的数字运动处理器 DMP(Digital Motion Processor),可用 I2C 接口连接一个第三方的数字传感器,比如磁力 计。扩展之后就可以通过其 I2C 或 SPI 接口输出一个 9 轴的信号。MPU-60X0 也可以通过其 I2C 接口连接非 惯性的数字传感器,比如压力传感器。 MPU-60X0 对陀螺仪和加速计分别用了三个 16 位的 ADC,将其测量的模拟量转化为可输出的数字量。为了精 确跟踪快速和慢速运动,传感器的测量范围是可控的,陀螺仪可测范围为250,500,1000,2000 / 秒(dps),加速计可测范围为2,4,8,16g(重力加速度)。 注:注:下图是采用串口助手将 MPU6050 采集的数据显示在上位机上,其中前三列输出为三维的加速度(这里的加 速度包括地球本身的重力加速度),后三列为三维的角速度。 但是但是这里的输出值并不是真正的加速度和角速度的值,上面说过,MPU 是一个 16 位 AD 量程可程控的设备,这 里设置的加速度传感器的测量量程为正负 2g(这里的 g 为重力加速度),陀螺仪的量程为正负 2000 /s。所以 要用下面的公式进行转化: 好了,有了上面的基础知识之后咱们就能尝试用 51 的 I2C 总线从 MPU6050 读取实时的 3 轴加速度和 3 轴角 速度了。由于 51 本身不带有 I2C 总线通信协议,所以我们要自己实现一个 I2C 通信协议,下面是我从网上找 的并稍加修改的一个 I2C 总线通信的代码: 1 #include 2 #include 3 4 typedef unsigned char uchar; 5 typedef unsigned short ushort; 6 typedef unsigned int uint; 7 8 /- 9 / 定义 MPU6050 内部地址 10 /- 11 #define SMPLRT_DIV 0x19 /陀螺仪采样率,典型值:0x07(125Hz) 12 #define CONFIG 0x1A /低通滤波频率,典型值:0x06(5Hz) 13 #define GYRO_CONFIG 0x1B /陀螺仪自检及测量范围, 典型值: 0x18(不自检, 2000deg/s) 14 #define ACCEL_CONFIG 0x1C /加速计自检、 测量范围及高通滤波频率, 典型值: 0x01(不自检,2G,5Hz) 15 #define ACCEL_XOUT_H 0x3B 16 #define ACCEL_XOUT_L 0x3C 17 #define ACCEL_YOUT_H 0x3D 18 #define ACCEL_YOUT_L 0x3E 19 #define ACCEL_ZOUT_H 0x3F 20 #define ACCEL_ZOUT_L 0x40 21 #define TEMP_OUT_H 0x41 22 #define TEMP_OUT_L 0x42 23 #define GYRO_XOUT_H 0x43 24 #define GYRO_XOUT_L 0x44 25 #define GYRO_YOUT_H 0x45 26 #define GYRO_YOUT_L 0x46 27 #define GYRO_ZOUT_H 0x47 28 #define GYRO_ZOUT_L 0x48 29 #define PWR_MGMT_1 0x6B /电源管理,典型值:0x00(正常启用) 30 #define WHO_AM_I 0x75 /IIC 地址寄存器(默认数值 0x68,只读) 31 #define SlaveAddress 0xD0 /IIC 写入时的地址字节数据,+1 为读取 32 33 /- 34 / I2C 总线通信函数 35 /- 36 void I2C_Start(); /I2C 起始信号 37 void I2C_Stop(); /I2C 停止信号 38 void I2C_SendACK(bit ack); /I2C 发送应答信号入口参数:ack (0:ACK 1:NAK) 39 bit I2C_RecvACK(); /I2C 接收应答信号 40 void I2C_SendByte(uchar dat); /向 I2C 总线发送一个字节数据 41 uchar I2C_RecvByte(); /从 I2C 总线接收一个字节数据 42 void Single_WriteI2C(uchar REG_Address,uchar REG_data);/向 I2C 设备写入一个字 节数据 43 uchar Single_ReadI2C(uchar REG_Address); /从 I2C 设备读取一个字 节数据 44 45 /- 46 / 通过 I2C 和 MPU6050 通信的函数 47 /- 48 void InitMPU6050(); /初始化 MPU6050 49 int GetData(uchar REG_Address); /合成数据 如果你没搞过硬件又从未听说过 I2C, 那么想想 socket 的握手再看看上面 3643 行的有关 ACK、 Send、 Write 的函数大概能明白 I2C 的功能。当我们实现 I2C 的通信函数之后就可以与带有 I2C 通信接口的芯片进行通信, 那么怎样通信呢?其实很简单你可以把每个芯片比做为一个巨大的储物柜, 储物柜里每个抽屉里存着相应的 东西,你想让佣人帮你去拿个东西,只要告诉佣人对应的抽屉号就行了。这里 I2C 总线相当于这个佣人,每个 抽屉相当于芯片中的寄存器,抽屉号相当于寄存器地址。当你想设置芯片的某些属性时是向对应的寄存器内写数 据,当想从芯片内获取相关数据时,就要通过 I2C 向对应的地址写数据然后接收芯片返回的数据。这里的 831 行为 MPU-6050 芯片内几个常用的寄存器地址,前四个常用来作为设置芯片工作属性,1528 共 14 个寄存器 地址用来获取传感器的 3 轴加速度、3 轴角速度和温度的数据(这里每一种信息都包括 H 和 L 两位,是由于 8 位表示不完该数据,于是分高低两部分) 这样我们便不难理解 InitMPU6050()和 GetData(uchar REG_Address)函数:初始化函数是向相应的地址写 初始化配置数据(关于 0x000x07 等意思请参看 MPU6050 寄存器版说明书),而 GetData 则是传入想获得 数据项的低地址, 然后连续读取当前地址数据和下一地址数据合成为想要的项目数据 (上面讲了数据分高低部分) 。 1 /- 2 /初始化 MPU6050 3 /- 4 void InitMPU6050() 5 6 Single_WriteI2C(PWR_MGMT_1, 0x00); /解除休眠状态 7 Single_WriteI2C(SMPLRT_DIV, 0x07); 8 Single_WriteI2C(CONFIG, 0x06); 9 Single_WriteI2C(GYRO_CONFIG, 0x18); 10 Single_WriteI2C(ACCEL_CONFIG, 0x01); 11 12 /- 13 /合成数据 14 /- 15 int GetData(uchar REG_Address) 16 17 uchar H,L; 18 H=Single_ReadI2C(REG_Address); 19 L=Single_ReadI2C(REG_Address+1); 20 return (H 2 / 询问当前值 3 / 4 / 如果解析到则返回真 5 public bool ask() 6 7 i = 0;/立刻将相应的 40 个字符复制出来 8 p_read_from = p_write - 40; 9 while (i 18 17 if (i = 18) return false; 18 i-; 19 data_Z = 0; 20 for (int j = 4; j -1; j-) 21 22 data_Z *= 10; 23 data_Z += (stri - j - 0); 24 25 if (stri - 5 = -) data_Z = -data_Z; 26 i -= 6; 27 28 data_Y = 0; 29 for (int j = 4; j -1; j-) 30 31 data_Y *= 10; 32 data_Y += (stri - j - 0); 33 34 if (stri - 5 = -) data_Y = -data_Y; 35 i -= 6; 36 37 data_X = 0; 38 for (int j = 4; j -1; j-) 39 40 data_X *= 10; 41
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号