感测综合设计.docx
《感测综合设计.docx》由会员分享,可在线阅读,更多相关《感测综合设计.docx(14页珍藏版)》请在冰豆网上搜索。
![感测综合设计.docx](https://file1.bdocx.com/fileroot1/2023-2/4/df86d842-e028-4233-b637-7a2b7d9655dc/df86d842-e028-4233-b637-7a2b7d9655dc1.gif)
感测综合设计
数理与信息工程学院
《感测技术基础》大作业报告
题目:
基于MPU6050的平衡板
专业班级:
电子信息工程131班
姓名:
邵文淦
学号:
13610120
指导老师:
蒋敏兰
日期:
2015年12月30日
成绩:
数理与信息工程学院电工电子实验中心制
基于MPU6050的平衡板
摘要
本系统采用MSP430F149单片机作为系统的核心,由MPU6050角度检测模块、电机驱动控制模块、液晶显示和电源部分组成。
主要实现了平面板的角度检测以及PID算法控制平板任意角度悬停的功能。
具体为单片机通过DMP读取MPU6050的角度值,从而输出PWM控制空心杯电机的转速实现平板的角度控制。
经测试系统能很好的完成设计功能。
关键词:
MSP430F149单片机;MPU6050角度传感器;PID算法
1.设计任务要求
1.1实现对平板的角度检测的功能。
1.2通过设定角度,控制平板在该角度悬停。
1.3通过实践,了解更多传感器知识以及学习如何使用传感器。
2.系统方案设计与论证
2.1主控芯片的选择
方案1:
采用高性能单片机CPU实现系统,如32位嵌入式CPUARM芯片作为控制系统核心。
采用该方案,虽然可以很好的解决角度检测与控制功能,但是ARM系统设计调试复杂,在短时间内难以很好地完成设计,故不宜采用此方案。
方案2:
采用STC89C52芯片作为主控制器。
STC89C52内部具有8KBROM存储空间,512字节数据存储空间,带有2K字节的EEPROM存储空间,与MCS-51系列单片机完全兼容,同时可以通过串口下载,但是该单片机需要专门的仿真器才能仿真,且不能通过内部资源产生PWM。
方案3:
用MSP430F149做控制芯片,它是TI公司生产的16位超低功耗微控制器,体积小,功能齐全,方便实用,而且可以在超低功耗模式下工作,对环境和人体辐射小。
在此系统中,采用MSP430F149单片机作为主控单片机更为实用。
综上考虑题目和设计要求,MSP430F149单片机指令简单,又能通过内部资源直接产生PWM,所以我们确定选择方案3。
2.2传感器选择
方案1:
采用WDD35D-4电位器式角度传感器,其独立线性度为±0.5%,阻值误差达到±15%,机械转角是360°(连续),理论电器转角为345正负2度。
其优点是测量角度简单,只需要通过判断它的阻值就能计算出相应的角度,缺点误差太大,且价格较贵,故不满足本次设计的要求。
方案2:
:
采用MPU6050角度传感器,MPU-6000为全球首例整合性6轴运动处理组件,它的角速度全格感测范围为±250、±500、±1000与±2000°/sec(dps),可准确追踪快速与慢速动作,并且,用户可程式控制的加速器全格感测范围为±2g、±4g±8g与±16g。
其内部数字运动处理(DMP)引擎可减少复杂的融合演算数据、感测器同步化、姿势感应等,计算出相应的三个横滚角、俯仰角、航向角,精度高,完全满足本设计的要求。
综合考虑到性价比、精度等因素,我选用了方案2。
3.理论分析
3.1计算角度值
首先,通过读取MPU6050内部的寄存器,我们就能够直接读取到x、y、z三个坐标轴的加速度Acceleration和角速度angularrate。
其次,通过对加速度的三角函数计算或者对角速度进行积分都能得到相应的角度值。
但是由于加速度的误差较大,而角速度的温漂较大,所以我们采用了一阶互补滤波的方法得到较为精准的角度值。
3.1.1根据加速度计算角度值
根据三个加速度值,通过对各个轴的反正切函数计算出角度。
其中,AX、AY、AZ分别是xyz轴的加速度。
具体的计算公式如下:
//式1:
z轴角度值
//式2:
x轴角度值
//式3:
y轴角度值
具体的计算函数程序如下:
shortMPU6050_Get_Angle(floatx,floaty,floatz,u8dir)
{
floattemp;
floatres=0;
switch(dir)
{
case0:
//与自然Z轴的角度
temp=sqrt((x*x+y*y))/z;
res=atan(temp);
break;
case1:
//与自然X轴的角度
temp=x/sqrt((y*y+z*z));
res=atan(temp);
break;
case2:
//与自然Y轴的角度
temp=y/sqrt((x*x+z*z));
res=atan(temp);
break;
}
returnres*1800/3.14;//把弧度转换成角度
}
3.1.2根据角速度计算角度值
根据对读取的角速度进行积分就能得到相应的角度。
本设计中由于不能对角速度在连续的时间上积分,但是只要间隔时间足够短,就能近似的得到积分值。
我在程序中采用了5ms的中断,dt为5ms。
//式4:
x轴角度值
3.1.3一阶互补滤波融合角度值
一阶互补滤波就是通过加速度计算的角度乘以一定的比重加上角速度积分的角度乘以一定的权重,所得的和就是融合后的角度,融合的效果可由权重调整。
本设计中取加速度权重K1为0.05,角速度权重为0.95。
Angle_x=K1*angle_1+(1-K1)*(angle2+gyro_y*dt)//一阶互补滤波
3.2PID控制算法分析
根据前面的方法我们可以计算出一个较为精确的角度值Angle_x,为了实现本设计中的第二个功能,还需要通过PID控制算法实现对Angle_x的闭环控制。
本设计中主要是将当前的实际角度与设定的角度构成一个差值Angle_error,将此差值作为PID控制器的输入端,再将控制器的输出作用于pwm,pwm控制电机转速实现平板到达设定的角度,即直至Angle_error为0,此时平板平衡不动。
PWM=LastPWM+p*(Angle_error-Last_Angle_error)+i*Last_Angle_error+d*(Angle_error-2*Last_Angle_error+PreAngle_error)//增量式PID控制算法
4.系统硬件电路设计
本设计的硬件部分主要由MPU6050传感器、MSP430控制器、OLED、电机驱动等及部分组成,MPU6050传感器负责采集加速度、角速度和角度信息,单片机负责接受传感器的数据,并将数据送到液晶上显示,同时根据角度值进行PID控制。
各个模块协调工作,完成系统的所有功能。
其系统框图和示意图如图一、二所示。
图1系统总设计框图
图2系统示意图
图3MPU6050接口电路
5.系统软件设计
图4软件设计流程图
系统的软件设计流程图如上图所示,首先让平板静止20s左右(让MPU6050初始化完成,读取零偏值),接着单片机开始读取计算角度值,本设计只涉及到平板的一维运动,故只需要读取横滚角即可(如图2中的θ)。
然后通过判断按键是否按下并且修改θ的设定值,进行PID控制,使平板始终处于设定的角度位置。
整个过程中,液晶不断的刷新显示设定角度与当前角度等参数。
6.测试结果及分析
通过实验测量,得到以下结果并进行数据分析
测试次数
1
2
3
4
5
实际角度
-60°
-30°
0°
30°
60°
测量角度
-60.5°
-30.1°
0.1°
30.4°
61°
设定角度
-60°
-30°
0°
30°
60°
PID控制后角度
-61.2°
-30.3°
0.1°
30.5°
61.3°
通过以上数据,有以下分析:
测量所得的角度值与实际的角度有一定的偏差,通过查阅资料及理论分析和验证,发现误差主要由以下因素造成:
采用角速度和加速度融合的方法及权重取值引起计算所得的角度值与实际角度值存在一定的偏差。
由于加速度存在误差且角速度温漂较大,所以融合前计算的角度本身就引入了误差。
由于机械结构的问题引入一定的误差。
同时,由表格中的数据我们可以知道PID控制的角度与设定的角度也存在一定的误差,切角度越大偏差也越大。
这主要是由于重力的影响导致。
7.设计中的问题与心得体会
问题:
由于MPU6050在初始化时需要充足的时间来校准,而我在初次编写程序的时候初始化时间不够,导致测得的角度值始终具有较大的抖动。
最终通过加长初始化时间成功解决。
角度读取之后没有除去零偏,导致控制不稳,通过去零偏得以解决。
心得体会:
经过几天的不懈努力,最后终于完成了软硬件、报告的全部任务。
经过多次测试,本设计运行稳定、可靠性高、抗干扰能力强。
同时,通过本次课程的设计与制作,使我对电子更加的热爱,有了更大的信心,也让我对传感器有了更加全面和深刻的认识。
让我懂得了传感器的设计原理,传感器的误差由来以及如何减小误差等等。
最后,感谢知道老师的耐心指导。
附件1:
系统实物图
附图1实物图
附件2:
系统整体电路图
附图2电机电路图
附图3电机电路图
附图4MPU6050传感器电路图
附件3:
核心代码
/***********************************************************
函数名称:
voidMPU6050_DMP_get_fifo(void)
函数功能:
MPU6050角度读取
入口参数:
无
出口参数:
无
备注:
在10ms定时中断中读取
***********************************************************/
voidMPU6050_DMP_get_fifo(void)
{
dmp_read_fifo(gyro,accel,quat,&sensor_timestamp,&sensors,&more);
if(sensors&INV_XYZ_GYRO)
send_packet(PACKET_TYPE_GYRO,gyro);
if(sensors&INV_XYZ_ACCEL)
send_packet(PACKET_TYPE_ACCEL,accel);
if(sensors&INV_WXYZ_QUAT)
{
q0=quat[0]/q30;
q1=quat[1]/q30;
q2=quat[2]/q30;
q3=quat[3]/q30;
Pitch=asin(2*q1*q3-2*q0*q2)*57.3;//pitch
Roll=atan2(2*q2*q3+2*q0*q1,-2*q1*q1-2*q2*q2+1)*57.3;//roll
Yaw=atan2(2*(q1*q2+q0*q3),q0*q0+q1*q1-q2*q2-q3*q3)*57.3;
}
}
/***********************************************************
函数名称:
voidPID_Control()
函数功能:
PID控制平板平衡在设定角度
入口参数:
无
出口参数:
无
备注:
采用位置式pid
***********************************************************/
voidPID_Control()
{
Roll_error=Roll_set-(Roll-Roll_offset);
/***********************PID控制*************************/
Roll_AddI=Roll_AddI+Roll_error;
Roll_Pout=Roll_error*Roll_1.P;
Roll_Iout=Roll_AddI*Roll_1.I;
Roll_Dout=(Roll_error-last_Roll_error)*Roll_1.D;
/*********************************************************/
Roll_PID_out=Roll_Pout+Roll_Iout+Roll_Dout;
pwm1=pwmZero1-Roll_PID_out;
pwm2=pwmZero2+Roll_PID_out;
last_Roll_error=Roll_error;
pre_Roll_error=last_Roll_error;
//pwm输出最大最小限定
if(pwm1>pwm1_max)pwm1=pwm1_max;
if(pwm1if(pwm2>pwm2_max)pwm2=pwm2_max;
if(pwm2last_pwm1=pwm1;
last_pwm2=pwm2;
//积分量限定
if(Roll_AddI>100)
{
Roll_AddI=100;
}
if(Roll_AddI<-100)
{
Roll_AddI=-100;
}
}
/***********************************************************
函数名称:
voidmain()
函数功能:
主函数
入口参数:
无
出口参数:
无
备注:
***********************************************************/
voidmain()
{
sys_init();
MPU6050_init();
OLED_Init();
Zero_avarage(100);
while
(1)
{
MPU6050_GetData_ACCEL();
MPU6050_GetData_GYRO();
ax=MPU6050.ACCEL_X-ACCEL_X_zero;
ay=MPU6050.ACCEL_Y-ACCEL_Y_zero;
az=MPU6050.ACCEL_Z-ACCEL_Z_zero;
gx=MPU6050.GYRO_X-GYRO_X_zero;
gy=-(MPU6050.GYRO_Y-GYRO_Y_zero);
gz=MPU6050.GYRO_Z-GYRO_Z_zero;
Angle_ACC(MPU6050.ACCEL_X,MPU6050.ACCEL_Y,MPU6050.ACCEL_Z);
complement_update_X(ax,gy);
send_HC_06_dat[0]=(s16)Accel_Angle_x;
send_HC_06_dat[1]=(s16)Gyro_AngSpeed_y;
send_HC_06_dat[2]=(s16)Angle_X;
send_HC_06_dat[3]=(s16)(X_angle_Out);
send8_HC_06(send_HC_06_dat,4);
keyScan_delay();
OLED_Display();
}
}