找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 10427|回复: 0
收起左侧

基于ARM倾角和加速度的检测装置的设计(MPU6050)

[复制链接]
ID:294212 发表于 2018-3-19 19:51 | 显示全部楼层 |阅读模式
该文件是本人课程设计希望对大家有所帮助。

测控技术与仪器专业

综合课程设计

基于ARM的加速度和倾检测装置的设计


学生姓名
发帖作者
学号
311404001919
班级
测控14-3
指导老师
完成日期
:  2018.3.9


理工大学机械与动力工程学院

0



2014级测控技术与仪器专业综合课程设计

摘要


设计了基于STM32F103RCT6的高精度倾斜角和加速度检测系统,系统硬件包括电源电路、六轴传感器(MPU6050)、2.8寸 TFT液晶显示屏、蓝牙模块以及其他辅助电路;软件上采用MDK5开发环境对ARM核心板进行编程、上位机进行数据显示;该系统可以对传感器倾斜角及加速度进行检测、通过手机接收MCU传感器数据、系统与上位机进行信息交互。程序先初始化 MPU6050 等外设,然后利用DMP库,初始化 MPU6050 及使能DMP,最后,在死循环里面不停读取:温度传感器、加速度传感器、陀螺仪、 DMP 姿态解算后的欧拉角等数据,通过串口上报给上位机(温度不上报),利用上位机软件,可以实时显示 MPU6050 的传感器状态曲线,实时显示 3D 姿态。可以通过 KEY0按键开启/关闭数据上传功能。同时,在 LCD模块上面显示温度和欧拉角等信息。



2014级测控技术与仪器专业综合课程设计
目  录

摘  要              I

1  设计任务书

1.1              涉及专业课程              (1)

1.2              设计任务              (1)

1.3              设计目标              (1)

1.4              本设计的主要功能              (2)

1.5              本章小结              (2)

2  设计论证及计划

2.1              课程设计背景及设计意义              (3)

2.2              设计采用软件及规划              (3)

2.3              本章小结              (4)

3  硬件系统设计

3.1              总体方案设计              (5)

3.2              元器件的选型及分析              (5)

3.3              系统模块功能及接口设计              (13)

3.4              本章小结              (15)

4  软件系统设计

4.1              软件系统总体方案设计              (16)

4.2              软件流程设计              (16)

4.3              程序代码设计与分析              (17)

4.4              本章小结              (23)

5  程序载入与调试

5.1              调试环境与工具              (24)

5.2              调试过程及现象分析              (24)

6  总结与展望

6.1              课程设计总结              (30)

6.2              工作展望              (30)

附  录A 设计程序              (31)

附  录 B 设计参考资料              (37)



2014级测控技术与仪器专业综合课程设计
1
     设计任务书



    •   涉及专业课程

本设计主要涉及的专业课程有:

1、单片机原理及应用

2、信号分析与处理

3、计算机控制技术

4、传感器技术

5、电子线路CAD

6、数字电子技术

7、复变函数与积分变换




    •   设计任务
1、基于MEMS集成电路检测倾斜角度案例:MEMS三轴陀螺仪的倾斜角检测应用;知识点包括MEMS陀螺仪的检测原理、检测电路、常用芯片型号,常见MEMS陀螺仪应用场合及注意事项。
2、基于MEMS集成电路检测加速度案例:MEMS三轴加速度计的加速度检测应用;知识点包括MEMS加速度的检测原理、检测电路、常用芯片型号,常见MEMS加速度计应用场合及注意事项。


    •   设计目标

根据设计任务并完成以下目标

  • 了解六轴传感器MPU6050工作原理以及其工作方式。
  • 熟练运用ARM完成对传感器的操作与控制;
  • 传感器数据通过串口通信在上位机上模拟显示;
  • 系统与手机通过蓝牙进行数据传输;
    •   本设计的主要功能
该系统主要可以完成对倾斜角及加速度的检测、数据通过蓝牙上传到手机、与上位机进行信息交互、上位机显示三轴方向加速度、显示三轴方向倾角、实时显示MPU6050的传感器状态曲线、数据3D模拟显示等功能。


    •   本章小结

结合所学课程和设计任务,制定了相应的工作任务,合理规划工作步骤。

2     设计论证及计划
市面上已经出现了众多以陀螺仪或加速度传感器为核心的智能设备,本次课程设计以此为课题具有可行性。

    •   课程设计背景及设计意义
现代工业生产设备的发展正在朝着向大型化,高速化,连续化和自动化的方向发展。其复杂程度日益增加,所涉及的知识范围广泛,不但包括机械设计、材料科学,现在又加入了计算机技术、光学、电路技术等,其不但价格昂贵,维护也同样麻烦。面对如此庞大的机械设备,我们必须需要一些仪器仪表来进行辅助检查与测试,我们希望这些仪器仪表具有一定的智能,不但要具有实时检测、自动报警、结果显示与保存等功能,还要具有体积小、重量轻、便于携带等优点。然而传统的机电仪表虽然具备某些优点,但其本身也是机、电、光、算的结合物,其使用与维护也相当的复杂,不利于当今机械设备的发展。
随着现代网络技术的发展和企业规模的快速扩大,功能独立的近距离的传统仪器测量已不能满足工业需求,远距离且大规模的测量仪器群将是未来发展的趋势。由于传统的仪器是模拟信号,不利于计算机的控制与运算,将不可能胜任现代企业管理及技术发展的需要。
由上分析,我们意识到传统的测量仪器在成本价格、制作技术、操作简便性等方面存在着不足,不能满足社会的需要。而近年来发展起来的虚拟仪器技术则在成本价格、制作技术、操作简便性方面有着不俗的表现,能很好的满足现代科学技术发展的需要,是仪器仪表未来发展的的重要方向。
六轴传感器MPU6050近年来广泛应用于各个领域,是未来智能设备中不可或缺的重要元件智能型手机、平板装置设备、手持型游戏产品、游戏机、3D遥控器、可携式导航设备。

    •   设计采用软件及设计规划
本课程设计是在MDK环境下完成的,采用C语言进行编程,完全采用面向对象的开发思想,具有很大的个人发挥空间,完成同一种功能可以从不同方面下手解决。MDK源自德国的KEIL公司,是RealView MDK的简称。在全球MDK被超过10万的嵌入式开发工程师使用。目前最新版本为:MDK5.14,该版本为 uVision5 IDE集成开发环境,是目前针对ARM处理器,尤其是Cortex M内核处理器的最佳开发工具。
设计规划:
针对此次课程设计,设计如下规划,如图2.1所示。

图2.1 课程设计规划

    •   本章小结
本章主要对课程设计的背景进行了介绍并对设计进行规划,制定出合理的工作流程。
3     硬件系统设计



    •   总体设计方案
倾角加速度检测系统,主要要完成对温度、加速度、倾斜角的采集、显示等工作。传统上采集加速度利用的是三轴加速度传感器而采集倾斜角利用的是三轴陀螺仪,针对本次课程设计要求成本相对较高。鉴于上述原因,本系统采用MPU6050六轴陀螺仪作为核心传感器。外部数据信号经 MPU6050将输入的模拟信号转换成数字信号,并通过IO口传送到单片机系统( STM32RCT6)。单片机系统将接收的数字信号译码处理,通过TFTLCD将温度及各个方向倾角显示出来,如图3.1说所示。


图3.1 设计整体架构(见附件)



    •   元器件的选型及分析

3.2.1MCU选型及分析

STM32F103RCT6是ST公司推出的一款以CortexM3为核心设计的32位单片机,远超8位51单片机,能出色完成设计任务。STM32的优异性体现在以下几个方面。
1.超低的价格。以8位机的价格,得到32位机,是STM32最大的优势。
2.超多的外设。STM32拥有包括:FSMC、TIMER、SPI、IIC、USB、CAN、IIS、SDIO、ADC、DAC、RTC、DMA等众多外设及功能,具有极高的集成度。
3.丰富的型号。STM32仅M3内核就拥有F100、F101、F102、F103、F105、F107、F207、F217等8个系列上百种型号,具有QFN、LQFP、BGA等封装可供选择。同时STM32还推出了STM32L和STM32W等超低功耗和无线应用型的M3芯片。
4.优异的实时性能。84个中断,16级可编程优先级,并且所有的引脚都可以作为中断输入。
5.杰出的功耗控制。STM32各个外设都有自己的独立时钟开关,可以通过关闭相应外设的时钟来降低功耗。
6.极低的开发成本。STM32的开发不需要昂贵的仿真器,只需要一个串口即可下载代码,并且支持SWD和JTAG两种调试口。SWD调试可以为你的设计带来跟多的方便,只需要2个IO口,即可实现仿真调试。

STM32F103RCT6原理图,如图3.2所示。

图3.2 MCU原理图

3.2.2 传感器选型及分析

设计要求完成对倾斜角、加速度和温度的检测,完成以上要求分别需要3轴陀螺仪、3轴加速度传感传感器、温度传感器考虑到成本等各方面因素本次课程设计选用具有多种功能的6轴传感器(MPU6050)来完成对数据的检测。
MPU6050 是 InvenSense 公司推出的全球首款整合性 6 轴运动处理组件,相较于多组件方案,免除了组合陀螺仪与加速器时之轴间差的问题,减少了安装空间。MPU6050 内部整合了 3 轴陀螺仪和 3 轴加速度传感器,并且含有一个第二 IIC 接口,可用于连接外部磁力传感器,并利用自带的数字运动处理器(DMP: Digital Motion Processor)硬件加速引擎,通过主 IIC 接口,向应用端输出完整的 9 轴融合演算数据。有了 DMP,我们可以使用InvenSense 公司提供的运动处理资料库,非常方便的实现姿态解算,降低了运动处理运算对操作系统的负荷,同时大大降低了开发难度。
MPU6050 的特点包括:
① 以数字形式输出 6 轴或 9 轴(需外接磁传感器)的旋转矩阵、四元数(quaternion)、欧拉角格式的融合演算数据(需 DMP 支持)。
② 具有 131 LSBs/° /sec 敏感度与全格感测范围为±250、±500、±1000 与±2000° /sec的 3 轴角速度感测器(陀螺仪)。
③ 集成可程序控制,范围为±2g、±4g、±8g 和±16g 的 3 轴加速度传感器。
④ 移除加速器与陀螺仪轴间敏感度,降低设定给予的影响与感测器的飘移。
⑤ 自带数字运动处理(DMP: Digital Motion Processing)引擎可减少 MCU 复杂的融合演算数据、感测器同步化、姿势感应等的负荷。
⑥ 运作时间偏差与磁力感测器校正演算技术,免除了须另外进行校正的需求
⑦ 自带一个数字温度传感器。
⑧ 带数字输入同步引脚(Sync pin)支持视频电子影像稳定技术与GPS。
⑨ 可程序控制的中断(interrupt),支持姿势识别、摇摄、画面放大缩小、滚动、快速下降中断、 high-G 中断、动作感应、触击感应、摇动感应功能。
⑩ VDD 供电电压为 2.5V±5%、 3.0V±5%、 3.3V±5%; VLOGIC 可低至 1.8V
⑪ 陀螺仪工作电流: 5mA,陀螺仪待机电流: 5uA;加速器工作电流: 500uA,加速器省电模式电流: 40uA@10Hz。
⑫ 自带 1024 字节 FIFO,有助于降低系统功耗。
⑬ 高达 400Khz 的 IIC 通信接口。
⑭ 超小封装尺寸: 4x4x0.9mm(QFN)。

MPU6050传感器实物图如3.3所示,其检测轴如图3.4所示。

3.3 MPU6050实物图


图3.4 MPU605检测轴方向


MPU6050的内部框图如图3.5所示。

图3.5 MPU内部框图
其中SCL和SDA是连接MCU的IIC接口,MCU通过这个IIC接口控MPU6050,另外还有一个IIC接口:AUX_CL和AUX_DA,这个接口可用来连接外部从设备,比如磁传感器,这样就可以组成一个9轴传感器。VLOGIC是IO口电压,该引脚最低可以到1.8V,我们一般直接接VDD即可。AD0是从IIC接口(接MCU)的地址控制引脚,该引脚控制IIC地址的最低位。如果接GND,则MPU6050的IIC地址是:0X68,如果接VDD,则是0X69。MPU6050外围电路如图3.6所示。

图3.6 MPU6050外围电路图
MPU6050工作原理:

陀螺仪检测也不是完全精确的,存在一定的误差。由于陀螺仪测量角度时使用积
图3.7 积分误差

分,会存在积分误差,如图3.7所示,若积分时间Dt越小,误差就越小。这十分容易理解,例如计算路程时,假设行车时间为 1 小时,我们随机选择行车过程某个时刻的速度Vt乘以1小时,求出的路程误差是极大的,因为行车的过程中并不是每个时刻都等于该时刻速度的,如果我们每5分钟检测一次车速,可得到Vt1、Vt2、Vt3-Vt12这12个时刻的车速,对各个时刻的速度乘以时间间隔(5分钟),并对这12个结果求和,就可得出一个相对精确的行车路程了,不断提高采样频率,就可以使积分时间Dt变小,降低误差。
同样地,提高陀螺仪传感器的采样频率,即可减少积分误差,目前非常普通的陀螺仪传感器的采样频率都可以达到8KHz,已能满足大部分应用的精度要求。
更难以解决的是器件本身误差带来的问题。例如,某种陀螺仪的误差是0.1度/秒,当陀螺仪静止不动时,理想的角速度应为0,无论它静止多久,对它进行积分测量
得的旋转角度都是0,这是理想的状态;而由于存在0.1度/秒的误差,当陀螺仪静止不动时,它采样得的角速度一直为0.1度/秒,若静止了1分钟,对它进行积分测量得的旋转角度为6度,若静止了1小时,陀螺仪进行积分测量得的旋转角度就是360度,即转过了一整圈。只有当正方向误差和负方向误差能正好互相抵消的时候,才能消除这种累计误差。
三轴加速度传感器检测原理:

由于直接用陀螺仪测量角度在长时间测量时会产生累计误差,引入了检测倾角的传感器。测量倾角最常见的例子是建筑中使用的水平仪,在重力的影响下,水平仪内的气泡能大致反映水柱所在直线与重力方向的夹角关系,利用图3.8中的T字型水平仪,可以检测出横滚角与俯仰角,而偏航角是无法以这样的方式检测的。在电子设备中,一般使用加速度传感器来检测倾角,它通过检测器件在各个方向的形变情况而采样得到受力数据,根据F=ma转换,传感器直接输出加速度数据,因而被称为加速度传感器。由于地球存在重力场,所以重力在任何时刻都会作用于传感器,当传感器静止的时候(实际上加速度为0),传感器会在该方向检测出加速度g,不能认为重力方向测出的加速度为g,就表示传感器在该方向作加速度为g的运动。
图3.8 T字型水平仪

当传感器的姿态不同时,它在自身各个坐标轴检测到的重力加速度是不一样利用
各方向的测量结果,根据力的分解原理,可求出各个坐标轴与重力之间的夹角,如图3.9所示。
图3.9 重力检测
因为重力方向是与地理坐标系的“天地”轴固连的,所以通过测量载体坐标系方向轴与重力方向的夹角即可求得它与地理坐标系的角度旋转关系,从而获知载体姿态。
加度传感器检测的误差
由于这种倾角检测方式是利用重力进行检测的,它无法检测到偏航角(Yaw),原理跟 T字型水平仪一样,无论如何设计水平仪,水泡都无法指示这样的角度。
另一个缺陷是加速度传感器并不会区分重力加速度与外力加速度,当物体运动的时候,它也会在运动的方向检测出加速度,特别在震动的状态下,传感器的数据会有非常大的数据变化,此时难以反应重力的实际值。
利用磁场检测角度
为了弥补加速度传感器无法检测偏航角(Yaw)的问题,我们再引入磁场检测传感器,它可以检测出各个方向上的磁场大小,通过检测地球磁场,它可实现指南针的功能,所以也被称为电子罗盘。由于地磁场与地理坐标系的“南北”轴“固联”,利用磁场检测传感器的指南针功能,就可以测量出偏航角(Yaw)了。
磁场检测器的误差
与指南针的缺陷一样,使用磁场传感器会受到外部磁场干扰,如载体本身的电磁场干扰,不地理同环境的磁铁矿干扰等等。
姿态融合与四元数
可以发现,使用陀螺仪检测角度时,在静止状态下存在缺陷,且受时间影响,而加速度传感器检测角度时,在运动状态下存在缺陷,且不受时间影响,刚好互补。假如我们同时使用这两种传感器,并设计一个滤波算法,当物体处于静止状态时,增大加速度数据的权重,当物体处于运动状时, 增大陀螺仪数据的权重,从而获得更准确的姿态数据。同理,检测偏航角,当载体在静止状态时,可增大磁场检测器数据的权重,当载体在运动状态时,增大陀螺仪和 GPS 检测数据的权重。这些采用多种传感器数据来检测姿态的处理算法被称为姿态融合。
在姿态融合解算的时候常常使用“四元数”来表示姿态,它由三个实数及一个虚数组成,因而被称之为四元数。使用四元数表示姿态并不直观,但因为使用欧拉角(即前面说的偏航角、横滚角及俯仰角)表示姿态的时候会有“万向节死锁”问题,且运算比较复杂,所以一般在数据处理的时候会使用四元数,处理完毕后再把四元数转换成欧拉角。

    •   系统模块功能及接口设计
该设计采用精英STM32F1开发板的IIC接口连接MPU6050模块,本章实验功能简介:程序先初始化MPU6050等外设,然后利用DMP库,初始化MPU6050及使DMP,最后,在死循环里面不停读取:温度传感器、加速度传感器、陀螺仪、DMP姿态解算后的欧拉角等数据,通过串口上报给上位机(温度不上报),利用上位机软件,可以实时显示 MPU6050 的传感器状态曲线,并显示3D姿态,可以通过KEY0 按键开启/关闭数据上传功能。同时,在 LCD 模块上面显示温度和欧拉角等信息。DS0来指示程序正在运行。

MPU6050引脚说明

该模块引出8个引脚功能说明如表3.1所示。
表3.1 MPU6050功能引脚说明
序号                     引脚名称                          说明
1              VCC              3.3/5V 电源输入
2              GND              地线
3              SCL              I2C从时钟信号线SCL(模块上已接上拉电阻)
4              SDA              I2C从数据信号线SDA(模块上已接上拉电阻)
5              XDA              I2C主串行数据信号线,用于外接传感器
6              XCL              I2C主串行数据信号线,用于外接传感器
7              AD0              从机地址设置引脚:接地或悬空,地址为:0X68
                            接VCC时,地址为:0X69
8              INT          中断输出引脚
其中的SDA/SCL、XDA/XCL通讯引脚分别为两组I2C信号线。当模块与外部主机通讯时,使用SDA/SCL,如与STM32芯片通讯;而XDA/XCL则用于MPU6050芯片与其它I2C传感器通讯时使用,例如使用它与磁场传感器连接,MPU6050模块可以把从主机SDA/SCL接收的数据或命令通过XDA/XCL引脚转发到磁场传感器中。但实际上这种功能比较鸡肋,控制麻烦且效率低,一般会直接把磁场传感器之类的I2C传感器直接与MPU6050挂载在同一条总线上(即都连接到SDA/SCL),使用主机直接控制。

所要用到的硬件资源主要有STM32开发板和MPU6050模块,它们的连接方式如图3.10所示。MPU6050模块与外部连接,引出了VCC、GND、IIC_SDA、IIC_SCL、MPU_INT和MPU_AD0等信号。其中,IIC_SDA和IIC_SCL带了4.7K上拉电阻,外部可以不用再加上拉电阻了,另外MPU_AD0自带了10K下拉电阻,当AD0 悬空时,默认IIC地址为(0X68)。模块的IIC_SCL、IIC_SDA分别连接在STM32的PC12、PC11上面。XDA和XCL是用来扩展连接磁力传感器使MPU6050转换为“九轴传感器”。
图3.10 连接方式图



    •   本章小结
本章主要介绍CMU的选型外设,以及各种传感器测角度的原理及缺陷,MPU6050利用姿态融合算法弥补传统传感器设计缺陷。MPU6050各个接口的功能介绍,单片机与MPU6050连接方式的设计。

4     软件系统设计



    •   软件系统总体方案设计
系统软件设计环境是MDK,软件设计由主程序模块、MPU6050程序模块、串口通讯模块以及液晶驱动程序模块组成。



    •   软件流程设计
1)初始化IIC接口
MPU6050采用IIC与STM32F1通信,所以我们需要先初始化与MPU6050连接的SDA和SCL数据线。
2)复位MPU6050
这一步让MPU6050内部所有寄存器恢复默认值,通过对电源管理寄存器1(0X6B)的bit7写1实现。复位后,电源管理寄存器1恢复默认值(0X40),然后必须设置该寄存器为0X00,以唤醒MPU6050,进入正常工作状态。
3)设置角速度传感器(陀螺仪)和加速度传感器的满量程范围
这一步,设置两个传感器的满量程范围(FSR),分别通过陀螺仪配置寄存器(0X1B)和加速度传感器配置寄存器(0X1C)设置。我们一般设置陀螺仪的满量程范围为±2000dps,加速度传感器的满量程范围位±2g。
4)设置其他参数
这里,我们还需要配置的参数有:关闭中断、关闭AUX IIC接口、禁止FIFO、设置陀螺仪采样率和设置数字低通滤波器(DLPF)等。本章我们不用中断方式读取数据,所以关闭中断,然后也没用到 AUX IIC 接口外接其他传感器,所以也关闭这个接口。分别通过中断使能寄存器(0X38)和用户控制寄存器(0X6A)控制。MPU6050可以使用FIFO存储传感器数据,不过本章我们没有用到,所以关闭所有FIFO通道,这个通过FIFO使能寄存器(0X23)控制,默认都是0(即禁止 FIFO),所以用默认值就可以了。陀螺仪采样率通过采样率分频寄存器(0X19)控制,这个采样率我们一般设置为50即可。数字低通滤波器(DLPF)则通过配置寄存器(0X1A)设置,一般设置DLPF为带宽的1/2即可。
5)配置系统时钟源并使能角速度传感器和加速度传感器
系统时钟源同样是通过电源管理寄存器1(0X6B)来设置,该寄存器的最低三位用于设置系统时钟源选择,默认值是0(内部8M RC震荡),不过我们一般设置为1,选择x轴陀螺PLL作为时钟源,以获得更高精度的时钟。同时,使能角速度传感器和加速度传感器,这两个操作通过电源管理寄存器2(0X6C)来设置,设置对应位为0即可开启。至此,MPU6050的初始化就完成了,可以正常工作了(其他未设置的寄存器全部采用默认值即可),接下来,我们就可以读取相关寄存器,得到加速度传感器、角速度传感器和温度传感器的数据了。



    •   程序代码设计与分析
      • 主函数代码设计与分析
  1. 以下是main函数中中最主要的部分程序
  2. 串口发送程序:
  3. void usart1_send_char(u8 c)
  4. {
  5.               while((USART1->SR&0X40)==0);//等待上一次发送完毕  
  6.               USART1->DR=c;               
  7. }
  8. //传送数据给上位机软件(
  9. void usart1_niming_report(u8 fun,u8*data,u8 len)
  10. {
  11.               u8 send_buf[32];
  12.               u8 i;
  13.               if(len>28)return;              //最多28字节数据
  14.               send_buf[len+3]=0;              //校验数置零
  15.               send_buf[0]=0X88;              //帧头
  16.               send_buf[1]=fun;              //功能字
  17.               send_buf[2]=len;              //数据长度
  18.               for(i=0;i<len;i++)send_buf[3+i]=data[i];                                          //复制数据
  19.               for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf[i];              //计算校验和            
  20.               for(i=0;i<len+4;i++)usart1_send_char(send_buf[i]);              //发送数据到串口1
  21. }
  22. //发送加速度传感器数据和陀螺仪数据
  23. //aacx,aacy,aacz:x,y,z三个方向上面的加速度值
  24. //gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值
  25. void mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)
  26. 通过串口上报结算后的姿态数据给电脑:
  27. //aacx,aacy,aacz:x,y,z三个方向上面的加速度值
  28. //gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值
  29. //roll:横滚角.单位0.01度。 -18000 - 18000 对应 -180.00  - 180.00度
  30. //pitch:俯仰角.单位 0.01度。-9000 - 9000 对应 -90.00 - 90.00 度
  31. //yaw:航向角.单位为0.1度 0 – 360。0度  对应 0 -> 360.0度
  32. void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz,short roll,short pitch,short yaw)
  33. LCD初始化:
  34. int main(void)
  35. {
  36.               u8 t=0,report=1;                            //默认开启上报
  37.               u8 key;
  38.               float pitch,roll,yaw;               //欧拉角
  39.               short aacx,aacy,aacz;              //加速度传感器原始数据
  40.               short gyrox,gyroy,gyroz;              //陀螺仪原始数据
  41.               short temp;                                          //温度                 
  42.               NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  43.               delay_init();                                //延时函数初始化               
  44.               uart_init(500000);                            //串口初始化为9600
  45.               usmart_dev.init(72);              //初始化USMART
  46.               LED_Init();                                            //初始化与LED连接的硬件接口
  47.               KEY_Init();                                          //初始化按键
  48.               LCD_Init();                                          //初始化LCD
  49.               MPU_Init();                                          //初始化MPU6050
  50.               POINT_COLOR=RED;                            //设置字体为红色
  51. 显示屏显示数据:
  52.               LCD_ShowString(30,50,200,16,16,"Wang Kai");            
  53.               LCD_ShowString(30,70,200,16,16,"MPU6050 TEST");            
  54.               LCD_ShowString(30,90,200,16,16,"HPU");
  55.               LCD_ShowString(30,110,200,16,16,"2018/3/12");
  56. while(mpu_dmp_init())
  57.               {
  58.                             LCD_ShowString(30,130,200,16,16,"MPU6050 Error");
  59.                             delay_ms(200);
  60.                             LCD_Fill(30,130,239,130+16,WHITE);
  61.                             delay_ms(200);
  62.               }
  63.               LCD_ShowString(30,130,200,16,16,"MPU6050 OK");
  64.               LCD_ShowString(30,150,200,16,16,"KEY0:UPLOAD ON/OFF");
  65.               POINT_COLOR=BLUE;//设置字体为蓝色
  66.               LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");            
  67.               LCD_ShowString(30,200,200,16,16," Temp:    . C");            
  68.               LCD_ShowString(30,220,200,16,16,"Pitch:    . C");            
  69.               LCD_ShowString(30,240,200,16,16," Roll:    . C");            
  70.               LCD_ShowString(30,260,200,16,16," Yaw :    . C");            
  71.               LCD_ShowString(30,280,200,16,16," Durriculum Design ");
  72.                             if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
  73.                             {
  74.                                           temp=MPU_Get_Temperature();              //得到温度值
  75.                                           MPU_Get_Accelerometer(&aacx,&aacy,&aacz);              //得到加速度传感器数据
  76.                                           MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);              //得到陀螺仪数据
  77.                             if(report)mpu6050_send_data(aacx,aacy,aacz,gyrox,gyroy,gyroz);//用自定义帧发送加速度和陀螺仪原始数据
  78. 原始数据处理:              if(report)usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10));
  79.                                           if((t%10)==0)
  80.                                           {
  81.                                                         if(temp<0)
  82.                                                         {
  83.                                                                       LCD_ShowChar(30+48,200,'-',16,0);                            //显示负号
  84.                                                         temp=-temp;                            //转为正数
  85.                                                         }else LCD_ShowChar(30+48,200,' ',16,0);//去掉负号
  86.                                                         LCD_ShowNum(30+48+8,200,temp/100,3,16);//显示整数部分                                                            LCD_ShowNum(30+48+40,200,temp%10,1,16);//显示小数部分                                                         temp=pitch*10;            
  87.                                           if(temp<0)
  88.                                                         {
  89.                                                         LCD_ShowChar(30+48,220,'-',16,0);                            //显示负号
  90.                                                         temp=-temp;                            //转为正数
  91.                                                         }else LCD_ShowChar(30+48,220,' ',16,0);//去掉负号
  92.                                                         LCD_ShowNum(30+48+8,220,temp/10,3,16);              //显示整数部分                                                            LCD_ShowNum(30+48+40,220,temp%10,1,16);              //显示小数部分
  93.                                                         temp=roll*10;
  94.                                                         if(temp<0)
  95.                                                         {
  96.                                                         LCD_ShowChar(30+48,240,'-',16,0);                            //显示负号
  97.                                                         temp=-temp;                            //转为正数
  98.                                                         }else LCD_ShowChar(30+48,240,' ',16,0);//去掉负号
  99.                                                         LCD_ShowNum(30+48+8,240,temp/10,3,16);              //显示整数部分
  100. LCD_ShowNum(30+48+40,240,temp%10,1,16);//显示小数部分
  101.                                                         temp=yaw*10;
  102.                                                         if(temp<0)
  103.                                                         {
  104.                                 LCD_ShowChar(30+48,260,'-',16,0);              //显示负号
  105.                                                                       temp=-temp;                            //转为正数
  106.                                                         }else LCD_ShowChar(30+48,260,' ',16,0);//去掉负号
  107.                                                         LCD_ShowNum(30+48+40,260,temp%10,1,16);//显示小数部分
  108.                                                         t=0;
  109.                                                         LED0=!LED0;//LED闪烁
  110.                                           }
  111.                             }

  112. 4.3.2 MPU6050程序分析

  113. MPU6050程序初始化:
  114. u8 MPU_Init(void)
  115. {
  116.               u8 res;
  117.               MPU_IIC_Init();//初始化IIC总线
  118.               MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);              //复位MPU6050
  119. delay_ms(100);
  120.               MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);              //唤醒MPU6050
  121.               MPU_Set_Gyro_Fsr(3);                                                                      //陀螺仪传感器,±2000dps
  122.               MPU_Set_Accel_Fsr(0);                                                                      //加速度传感器,±2g
  123.               MPU_Set_Rate(50);                                                                                    //设置采样率50Hz
  124.               MPU_Write_Byte(MPU_INT_EN_REG,0X00);              //关闭所有中断
  125.               MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);//I2C主模式关闭
  126.               MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);              //关闭FIFO
  127.               MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);//INT引脚低电平有效
  128.               res=MPU_Read_Byte(MPU_DEVICE_ID_REG);
  129.               if(res==MPU_ADDR)//器件ID正确
  130.               {
  131.                             MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);//设置CLKSEL,PLL X轴为参考
  132.                             MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);//加速度与陀螺仪都工作
  133.                             MPU_Set_Rate(50);                                                                      //设置采样率为50Hz
  134.               }else return 1;
  135.               return 0;
  136. }
  137. //设置MPU6050陀螺仪传感器满量程范围
  138. //fsr:0,±250dps;1,±500dps;2,±1000dps;3,±2000dps
  139. //返回值:0,设置成功
  140. //    其他,设置失败
  141. u8 MPU_Set_Gyro_Fsr(u8 fsr)
  142. {
  143.               return MPU_Write_Byte(MPU_GYRO_CFG_REG,fsr<<3);//设置陀螺仪满量程范围
  144. }
  145. 设置MPU6050加速度传感器满量程范围
  146. //fsr:0,±2g;1,±4g;2,±8g;3,±16g
  147. //返回值:0,设置成功
  148. //    其他,设置失败
  149. u8 MPU_Set_Accel_Fsr(u8 fsr)
  150. {
  151.               return MPU_Write_Byte(MPU_ACCEL_CFG_REG,fsr<<3);//设置加速度传感器满量程范围
  152. }
  153. //设置MPU6050的数字低通滤波器
  154. //lpf:数字低通滤波频率(Hz)
  155. //返回值:0,设置成功
  156. // 其他,设置失败
复制代码




    •   本章小结
本章主要是程序代码的设计,根据硬件设计相应的程序,完成设计要求任务。分析程序主函数、LCD函数、串口函数。

5     程序载入与调试



    •   调试环境与工具

MDK源自德国的KEIL公司,是RealView MDK的简称。在全球MDK被超过10万的嵌入式开发工程师使用。目前最新版本为:MDK5.14,该版本使用uVision5 IDE 集成开发环境,是目前针对ARM处理器,尤其是Cortex M 内核处理器的最佳开发工具。MDK5 向后兼容MDK4和MDK3等,以前的项目同样可以在MDK5上进行开发(但是头文件方面得全部自己添加),MDK5同时加强了针对 Cortex-M微控制器开发的支持,并且对传统的开发模式和界面进行升级,MDK5由两个部分组成:MDK Core 和 Software Packs。其中,Software Packs 可以独立于工具链进行新芯片支持和中间库的升级。如图5.1所示。

图5.1 MDK架构图

从上图可以看出,MDK Core又分成四个部分:uVision IDE with Editor(编辑器),ARM C/C++Compiler(编译器),Pack Installer(包安装器),uVision Debugger with Trace(调试跟踪器)。



    •   调试过程及现象分析
      • 硬件连接
主要涉及的硬件有USB TO TTL模块、MPU6050模块、STM32F103RCT6最小系统板、TFT液晶显示器,如图5.1所示。


图5.2 系统连接图


实物连接图,如图5.3所示。

USBTOTTL串口及蓝牙接口说明:
VCC接VCC;
GND接GND;
TXD接RXD;
RXD接TXD;
MPU6050接口说明
VCC接VCC;
GND接GND;
SCL接PC12;
SDA接PC11;
INT和AD0未用到,而XDA和XCL是用来接扩展。

5.2.2程序烧录


烧录前将核心板与电脑通过仿真器连接起来,把仿真器把仿真器用 USB 线连接电脑,如果仿真器的灯亮则表示正常,可以使用。然后把仿真器的另外一端连接到开发板,给开发板上电,然后就可以通过软件MDK给开发板下载程序。如图5.4所示及实物连接图如5.5所示。

图5.4 仿真器与电脑和开发板连接方式

工程软件配置如图5.6所示。


图5.6 工程配置图







      • 实验现象及分析
在代码编译成功之后,通过仿真器下载代码到STM32F103开发板上,可以看到 LCD显示如图5.7所示。

屏幕显示了MPU6050的温度、俯仰角(pitch)、横滚角(roll)和航向角(yaw)的数值。晃动MPU6050传感器各角度随之变化。另外,通过按KEY0可以开启或关闭数据上报,开启状态下,打开电脑端上位机,接收STM32F1上传的数据,从而图形化显示传感器数据。传感器数据波形显示如图5.8所示。

图5.8 上位机测试图

以上就是波形化显示我们通过 mpu6050_send_data 函数发送的数据,采用 A1功能帧发送,总共 6 条线(Series1~6)显示波形,全部来自 A1 功能帧, int16 数据格式,Series1~6 分别代表:加速度传感器 x/y/z 和角速度传感器(陀螺仪)x/y/z方向的原始数据。图 35.4.3 则 3D 显示了我们开发板的姿态,通过usart1_report_imu函数发送的数据显示,采用飞控显示帧格(AF)式上传,同时还显示了加速度陀螺仪等传感器的原始数据。在界面左侧的“基本功能”选项卡里面设置好 USB 虚拟串口号以及波特率(500000),然后在“飞控状态”选项卡里面依次在右下方选上“高级收码”,“波形显示”和“打开串口”三个按钮即可。最后用USMART读写 MPU6050 的任何寄存器,来调试代码。用 USMART 调试的时候,先按 KEY0 关闭数据上传功能,否则会收到很多乱码,波特率设置为:500Kbps(设置方法: XCOM 在关闭串口状态下,选择自定义波特率,然后输入:500000,再打开串口)。图5.9 是数据利用上位机模型化成立后的结果。

ACC代表加速度值,accx,accy,accz分别代表x,y,z三个方向上的加速度值。
GYRO代表陀螺仪值,gyrox, gyroy, gyroz分别代表下、x,y,z三个方向上的陀螺仪值。
6     总结与展望

课程设计总结

本课程设计经历了两周的努力。课程设计主要完成内容如下:
(1)本系统所设计的角度加速度检测装置完成了对温度角度加速度的实时检测,并完成了与上位机通信的功能,除此之外,还能通过蓝牙与手机完成数据传输。
(2)算法方面不够完善,测试数据有误差。硬件使用杜邦线连接,易受到外界影响。

工作展望

本次课程设计从获得题目开始便着手准备,首先查询相关传感器原理,选取几种传感器进行比较,最后确定MPU6050作为主要传感器,其次是MCU的选取,考虑到51的局限性最后确定STM32F103RCT6作为核心。通过MDK进行程序编写,下载器选择了Jlink作为下载工具将程序载入核心板。通过在上位机上进行数据调试。在本次课程设计过程中得到了李老师以及许多同学的帮助,感谢那些提供过帮助的李老师和同学。
课程设计还有很多地方需要改进,在以后的学习生活中去尝试“九轴传感器”进行更多数据的测试。

  1. void usart1_send_char(u8 c)
  2. {
  3.               while((USART1->SR&0X40)==0);//等待上一次发送完毕
  4.               USART1->DR=c;
  5. }
  6. //传送数据给匿名四轴上位机软件(V2.6版本)
  7. //fun:功能字. 0XA0~0XAF
  8. //data:数据缓存区,最多28字节!!
  9. //len:data区有效数据个数
  10. void usart1_niming_report(u8 fun,u8*data,u8 len)
  11. {
  12.               u8 send_buf[32];
  13.               u8 i;
  14.               if(len>28)return;              //最多28字节数据
  15.               send_buf[len+3]=0;              //校验数置零
  16.               send_buf[0]=0X88;              //帧头
  17.               send_buf[1]=fun;              //功能字
  18.               send_buf[2]=len;              //数据长度
  19.               for(i=0;i<len;i++)send_buf[3+i]=data[i];                                          //复制数据
  20.               for(i=0;i<len+3;i++)send_buf[len+3]+=send_buf[i];              //计算校验和            
  21.               for(i=0;i<len+4;i++)usart1_send_char(send_buf[i]);              //发送数据到串口1
  22. }
  23. //发送加速度传感器数据和陀螺仪数据
  24. //aacx,aacy,aacz:x,y,z三个方向上面的加速度值
  25. //gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值
  26. void mpu6050_send_data(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz)
  27. {
  28.               u8 tbuf[12];
  29.               tbuf[0]=(aacx>>8)&0XFF;
  30.               tbuf[1]=aacx&0XFF;
  31.               tbuf[2]=(aacy>>8)&0XFF;
  32.               tbuf[3]=aacy&0XFF;
  33.               tbuf[4]=(aacz>>8)&0XFF;
  34.               tbuf[5]=aacz&0XFF;
  35.               tbuf[6]=(gyrox>>8)&0XFF;
  36.               tbuf[7]=gyrox&0XFF;
  37.               tbuf[8]=(gyroy>>8)&0XFF;
  38.               tbuf[9]=gyroy&0XFF;
  39.               tbuf[10]=(gyroz>>8)&0XFF;
  40.               tbuf[11]=gyroz&0XFF;
  41.               usart1_niming_report(0XA1,tbuf,12);//自定义帧,0XA1
  42. }            
  43. //通过串口1上报结算后的姿态数据给电脑
  44. //aacx,aacy,aacz:x,y,z三个方向上面的加速度值
  45. //gyrox,gyroy,gyroz:x,y,z三个方向上面的陀螺仪值
  46. //roll:横滚角.单位0.01度。 -18000 -> 18000 对应 -180.00  ->  180.00度
  47. //pitch:俯仰角.单位 0.01度。-9000 - 9000 对应 -90.00 -> 90.00 度
  48. //yaw:航向角.单位为0.1度 0 -> 3600  对应 0 -> 360.0度
  49. void usart1_report_imu(short aacx,short aacy,short aacz,short gyrox,short gyroy,short gyroz,short roll,short pitch,short yaw)
  50. {
  51.               u8 tbuf[28];
  52.               u8 i;
  53.               for(i=0;i<28;i++)tbuf[i]=0;//清0
  54.               tbuf[0]=(aacx>>8)&0XFF;
  55.               tbuf[1]=aacx&0XFF;
  56.               tbuf[2]=(aacy>>8)&0XFF;
  57.               tbuf[3]=aacy&0XFF;
  58.               tbuf[4]=(aacz>>8)&0XFF;
  59.               tbuf[5]=aacz&0XFF;
  60.               tbuf[6]=(gyrox>>8)&0XFF;
  61.               tbuf[7]=gyrox&0XFF;
  62.               tbuf[8]=(gyroy>>8)&0XFF;
  63.               tbuf[9]=gyroy&0XFF;
  64.               tbuf[10]=(gyroz>>8)&0XFF;
  65.               tbuf[11]=gyroz&0XFF;            
  66.               tbuf[18]=(roll>>8)&0XFF;
  67.               tbuf[19]=roll&0XFF;
  68.               tbuf[20]=(pitch>>8)&0XFF;
  69.               tbuf[21]=pitch&0XFF;
  70.               tbuf[22]=(yaw>>8)&0XFF;
  71.               tbuf[23]=yaw&0XFF;
  72.               usart1_niming_report(0XAF,tbuf,28);//飞控显示帧,0XAF
  73. }  


  74. int main(void)
  75. {
  76.               u8 t=0,report=1;                                          //默认开启上报
  77.               u8 key;
  78.               float pitch,roll,yaw;                             //欧拉角
  79.               short aacx,aacy,aacz;                            //加速度传感器原始数据
  80.               short gyrox,gyroy,gyroz;              //陀螺仪原始数据
  81.               short temp;                                                                      //温度                 
  82.             
  83.               NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  84.               delay_init();                                //延时函数初始化               
  85.               uart_init(500000);                            //串口初始化为9600
  86.               usmart_dev.init(72);                            //初始化USMART
  87.               LED_Init();                                                                        //初始化与LED连接的硬件接口
  88.               KEY_Init();                                                                      //初始化按键
  89.               LCD_Init();                                                                         //初始化LCD
  90.               MPU_Init();                                                                      //初始化MPU6050
  91.               POINT_COLOR=RED;                                          //设置字体为红色
  92.               LCD_ShowString(30,50,200,16,16,"Wang Kai");            
  93.               LCD_ShowString(30,70,200,16,16,"MPU6050 TEST");            
  94.               LCD_ShowString(30,90,200,16,16,"HPU");
  95.               LCD_ShowString(30,110,200,16,16,"2018/3/12");
  96.               while(mpu_dmp_init())
  97.               {
  98.                             LCD_ShowString(30,130,200,16,16,"MPU6050 Error");
  99.                             delay_ms(200);
  100.                             LCD_Fill(30,130,239,130+16,WHITE);
  101.                             delay_ms(200);
  102.               }
  103.               LCD_ShowString(30,130,200,16,16,"MPU6050 OK");
  104.               LCD_ShowString(30,150,200,16,16,"KEY0:UPLOAD ON/OFF");
  105.               POINT_COLOR=BLUE;//设置字体为蓝色
  106.               LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");            
  107.               LCD_ShowString(30,200,200,16,16," Temp:    . C");            
  108.               LCD_ShowString(30,220,200,16,16,"Pitch:    . C");            
  109.               LCD_ShowString(30,240,200,16,16," Roll:    . C");            
  110.               LCD_ShowString(30,260,200,16,16," Yaw :    . C");            
  111.               LCD_ShowString(30,280,200,16,16," Durriculum Design ");
  112.               while(1)
  113.               {
  114.                             key=KEY_Scan(0);
  115.                             if(key==KEY0_PRES)
  116.                             {
  117.                             report=!report;
  118.                             if(report)LCD_ShowString(30,170,200,16,16,"UPLOAD ON ");
  119.                             else LCD_ShowString(30,170,200,16,16,"UPLOAD OFF");
  120.                             }
  121.                             if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
  122.                             {
  123.                             temp=MPU_Get_Temperature();              //得到温度值
  124.                             MPU_Get_Accelerometer(&aacx,&aacy,&aacz);              //得到加速度传感器数据
  125.                             MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);              //得到陀螺仪数据
  126.                             if(report)mpu6050_send_data(aacx,aacy,aacz,gyrox,gyroy,gyroz);//用自定义帧发送加速度和陀螺仪原始数据
  127.               if(report)usart1_report_imu(aacx,aacy,aacz,gyrox,gyroy,gyroz,(int)(roll*100),(int)(pitch*100),(int)(yaw*10));
  128.                                           if((t%10)==0)
  129.                                           {
  130.                                                         if(temp<0)
  131.                                                         {
  132.                                                         LCD_ShowChar(30+48,200,'-',16,0);                            //显示负号
  133.                                                         temp=-temp;                            //转为正数
  134.                                                         }else LCD_ShowChar(30+48,200,' ',16,0);//去掉负号
  135.                                                         LCD_ShowNum(30+48+8,200,temp/100,3,16);//显示整数部分
  136.                                                         LCD_ShowNum(30+48+40,200,temp%10,1,16);//显示小数部分
  137.                                                         temp=pitch*10;
  138.                                                         if(temp<0)
  139.                                                         {
  140.                                                                       LCD_ShowChar(30+48,220,'-',16,0);                            //显示负号
  141.                                                                       temp=-temp;                            //转为正数
  142.                                                         }else LCD_ShowChar(30+48,220,' ',16,0);//去掉负号
  143.                                                         LCD_ShowNum(30+48+8,220,temp/10,3,16);              //显示整数部分
  144.                                                         LCD_ShowNum(30+48+40,220,temp%10,1,16);//显示小数部分
  145.                                                         temp=roll*10;
  146.                                                         if(temp<0)
  147.                                                         {
  148.                                                                       LCD_ShowChar(30+48,240,'-',16,0);              //显示负号
  149.                                                                       temp=-temp;                            //转为正数
  150.                                                         }else LCD_ShowChar(30+48,240,' ',16,0);//去掉负号
  151.                                                         LCD_ShowNum(30+48+8,240,temp/10,3,16);              //显示整数部分
  152.                                                         LCD_ShowNum(30+48+40,240,temp%10,1,16);//显示数部分
  153.                                                         temp=yaw*10;
  154.                                                         if(temp<0)
  155.                                                         {
  156.                                                                       LCD_ShowChar(30+48,260,'-',16,0);              //显示负号
  157.                                                                       temp=-temp;              //转为正数
  158.                                                         }else LCD_ShowChar(30+48,260,' ',16,0);//去掉负号
  159.                                                         LCD_ShowNum(30+48+8,260,temp/10,3,16);//显示整数部分
  160.                                                         LCD_ShowNum(30+48+40,260,temp%10,1,16);//显示小数部分
  161.                                                         t=0;
  162.                                                         LED0=!LED0;//LED闪烁;
  163.                                           }
  164.                             }
  165.                             t++;
  166.               }              
  167. }
复制代码


完整的Word格式文档51黑下载地址:
倾角加速度检测.doc (1.3 MB, 下载次数: 34)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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