资源描述
精选优质文档-倾情为你奉上 2014年电子设计竞赛四旋翼自主飞行器(G题) 2013年9月11日目录摘要 关键词1一系统方案21.1 控制系统的选择 21.2 飞行姿态控制的论证与选择.21.3 电机的选择 21.4 高度测量模块的论证与选择.21.5 电机调速模块的选择21.6 循迹模块的方案选择21.7 薄铁片拾取的方案的论证与选择 21.8 角速度与角加速度测量模块选择 3二设计与论证3 2.1控制方法设计3 2.1.1降落及飞行轨迹控制设计3 2.1.2飞行高度控制设计4 2.1.3飞行姿态控制设计4 2.1.4铁片拾取与投放控制设计4 2.2参数计算5三理论分析与计算. 53.1Pid控制算法分析.5.3.2飞行姿态控制单元6四电路与程序设计7 4.1系统组成 7 4.2 原理框图 7 4.3电路图 8 4.4系统软件与流程图9五测试方案与测试条件 11 5.1测试方案115.2测试条件11六结论 11附录12附一:元器件明细表12附二:仪器设备清单12附三:源程序12摘要:本系统由数据采集、数据信号处理和飞行姿态和航向控制部分组成。系统选用STC89C52单片机作为主控芯片,对从MPU-6050芯片读取到的一系列数据进行PID算法处理并给飞行器的电调给出相应指令从而达到对飞行器的飞行姿态的控制。采用MPU-6050芯片采集四旋翼飞行器的三轴角速度和三轴角加速度数据。用红外传感器来检测出黑色指示线,以保证飞行器不脱离指定飞行区域及达到指定圆形区域。利用超声波传感器来检测飞行器与地面的距离,以保证飞行器能越过一米示高线。利用电磁铁来吸取和投放铁片。关键词:STC89C52单片机 MPU-6050模块 激光传感器循迹 电磁铁拾取铁片 超声波测距定高 PID算法一 系统方案本系统主要由控制模块、薄铁片拾取、高度测量模块、电机调速模块、循迹模块、角速度和角加速度模块组成,下面分别论证这几个模块的选择。1.1控制系统的选择 STC89C52RC单片机作为主控芯片来控制飞行器的飞行姿态与方向。1.2 飞行姿态控制的论证与选择 方案一:单片机将从MPU-6050中读取出来的飞行原始数据进行PID算法运算,得到当前的飞行器欧拉角,单片机得到这个欧拉角后根据欧拉角的角度及方向输出相应的指令给电调,从而达到控制飞行器平稳飞行的目的方案二:单片机将从MPU-6050中读取出来的飞行原始数据进行PID算法运算,得到当前飞行器的四元数,单片机再将数据融合,并对电调发出相应指令,从而达到控制飞行器的飞行姿态的目的。但四元数法需要进行大量的运算,且运算复杂。从算法的复杂程度及我们对算法的熟悉程度,我们选择方案一。1.3电机的选择方案一:采用有刷电机。有刷电机采用机械转向,寿命短,噪声大,产生电火花,效率低。它长期使用碳刷磨损严重,较易损坏,同时磨损产生了大量的碳粉尘,这些粉尘落轴承中,使轴承油加速干涸,电机噪声进一步增大。有刷电机连续使用一定时间就需更换电机内碳刷。方案二:采用无刷电机。无刷电机以电子转向取代机械转向。无机械摩擦,无摩擦,无电火花,免维护且能做到更加密封等特点所以技术上要优于有刷电机。考虑到各方面,我们采用无刷电机,选用新西达A2212无刷电机。1.4高度测量模块的论证与选择 方案一:采用bmp085气压传感器测量大气压并转换为海拔高度,把当前的海拔测量值减去起飞时的海拔值即得飞机的离地高度。但芯片价格较贵,误差较大,而且以前也没用过这个芯片。方案二:采用HC-SR04超声波传感器测量飞行器当前的飞行高度。考虑到对元件的熟悉程度、元件的价格和程序的编写,选择方案二。1.5电机调速模块的选择 由于本四旋翼飞行器选用的是无刷电机,所以电调只能选用无刷电机的电调,自己做电调需要的时间长,而且可能不稳定,所以直接用的是成品电调,我们选用电机配套的新西达A2212电调。1.6循迹模块的选择 普通的红外传感器检测的距离很近,无法在离地面一米以上的距离检测出地面的黑线,所以我们选择了漫反射远距离激光传感器,来检测指示线。1.7薄铁片拾取的选择方案一:在飞行器起飞时由系统控制机械臂拾取起铁片,到达B区放松机械臂,投下薄铁片。缺点:机械臂重量大,对飞行器的飞行姿态影响较大,薄铁片厚度非常小,不易拾取。 方案二:采用电磁铁拾取,用瑞萨MCU控制电磁铁,在飞行器起飞时吸取铁片,到B区后投下铁片。优点:电磁铁体积小而且有较强的拾取能力而且好操作方便。 综上所述,我们选择用经济又灵活的电磁铁作为薄铁片的拾取工具,采用方案二1.8角速度与加速度测量模块选择 方案一:选用MMA7361 角度传感器测量飞行器的的与地面的角度,返回信号给单片机处理,从而保持飞行器的平衡。 方案二:用MPU-6050芯片采集飞行器的飞行数据,过采用MPU-6050整合的3轴陀螺仪、3轴加速器,功能MPU-6000(6050)整合了3轴陀螺仪、3轴加速器,并含可藉由第二个I2C端口连接其他厂牌之加速器、磁力传感器、或其他传感器的数位运动处理(DMP: Digital Motion Processor)硬件加速引擎,由主要I2C端口以单一数据流的形式,向应用端输出完整的9轴融合演算技术InvenSense的运动处理资料库,可处理运动感测的复杂数据,降低了运动处理运算对操作系统的负荷,并为应用开发提供架构化的API。免除了组合陀螺仪与加速器时之轴间差的问题,减少了大量的包装空间。 综上,选择方案二。二 设计与论证2.1控制方法设计 2.1.1降落及飞行轨迹控制 由于题中有指示线,所我们采用漫反射红外开关来识别地面的指示线,红外模块将识别指示线后的信号以高低电平的方式传给单片机,单片机对信号做出反应,控制电调,从而控制飞行器飞行轨迹。程序流程图如图一 图一 图二 2.1.2飞行高度控制 飞行高度的采集采用超声波模块来实现,通过超声波发出时开始计时,收4到返回信号时停止计时,单片机利用声音在空气中的传播速度与时间的数学关系来计算出飞行器距离地面的时间,从而控制飞行器的飞行高度达到我们所需的高度。程序流程图如图二。 2.1.3飞行姿态控制 通过MPU6050模块来测量当前飞行器的三轴加速度和三轴角加速度,利用瑞萨单片机的IIC协议从MPU6050中读取出数据,解读飞行器的飞行姿态,并经过PID算法程序来对数据进行处理,得到当前欧拉角的值,并将处理后的信号传给电调,控制电机的转速,从而达到控制飞行器的飞行姿态的目的。程序流程图如图三。 2.1.4薄铁片拾取与投放控制 根据电磁铁的通电具有磁性,断电磁性消失的原理,从A起飞时我们让单片机控制电磁铁通电,让飞行器吸取薄铁片飞向B区,到达B区后让电磁铁断电,从而投下薄铁片,让其落到B区。程序流程图如图四。 图三 图四2.2参数计算 本系统最主要的参数计算是对MPU-6050等传感器采集的原始飞行数据进行处理。 单片机从MPU-6050芯片获取的数据是飞行器的三轴角速度和三轴角加速度,MCU对数据进行PID算法处理可以得到飞行器当前的飞行姿态,PID是比例,积分,微分的缩写。比例调节作用:是按比例反应系统的偏差,系统一旦出现了偏差,比例调节立即产生调节作用用以减少偏差。比例作用大,可以加快调节,减少误差,但是过大的比例,使系统的稳定性下降,甚至造成系统的不稳定。积分调节作用:是使系统消除稳态误差,提高无差度。因为有误差,积分调节就进行,直至无差,积分调节停止,积分调节输出一常值。积分作用的强弱取决与积分时间常数Ti,Ti越小,积分作用就越强。反之Ti大则积分作用弱,加入积分调节可使系统稳定性下降,动态响应变慢。积分作用常与另两种调节规律结合,组成PI调节器或PID调节器。三 理论分析与计算3.1Pid控制算法分析由于四旋翼飞行器由四路电机带动两对反向螺旋桨来产生推力,所以如何保证电机在平稳悬浮或上升状态时转速的一致性及不同动作时各个电机转速的比例关系是飞行器按照期望姿态飞行的关键。所以这里我们采用到pid控制理论把飞机的当前姿态调整到期望姿态。比例积分微分被控对象r(t)e(t)u(t)C(t)_Pid控制是通过姿态采集模块发送回来的数据与期望姿态进行比对,如果存在误差,就对误差进行比例、积分、微分的调整,再将调整后的值加到当前电机上,从而达到调整的目的。比例调节的反应速度较快,而且调节作用明显,飞机出现俯仰和翻滚时能快速调节回来,但是稳定性较差,往往会调节过火;积分调节可以消除长期误差,排除外界因素的干扰,但是同样会降低系统整体的稳定性,使飞机发生震荡;微分调节可以预测被控设备的将来状态,及时的进行调整,而且对比例调节有抑制作用,加强单比例调节的稳定性,排除调节过度的问题。所以通过pid控制可以完全考虑到整个系统的过去、现在、将来,以使系统达到稳定。飞行器油门90º-90º0ºPid调节3-3量化转化3.2飞行姿态控制单元飞行器模拟图如下图,姿态控制是通过陀螺仪模块进行数据的采集,根据它采集回来的俯仰角(pitch),翻滚角(roll),四旋翼采用十字型连接,这样的话能明确分离俯仰姿态和翻滚姿态,进行分别控制。这时如果飞机处于俯仰状态就调机头和机尾的电机,那边高就减小那边电机的转速,相应的那边低则加大那边电机的转速。如果飞机处于翻滚状态,则调左右电机。24 31左右头尾PitchRoll头尾Yaw四 电路与程序设计4.1系统组成 本四旋翼飞行系统由瑞萨最小系统板、MPU-6050芯片模块、红外循迹、超声波模块和电磁铁构成,由瑞萨单片机用PID算法处理外围传感器传回来的数据,用处理后的数据来控制飞行器的外围器件从而试飞行器能沿着指示线飞行。4.2原理框图激光传感器测指示线STC89C52 MCU电磁铁电调电机超声波模块MPU-60504.3电路图 MPU6050电路图 电源模块电路4.4系统软件与程序流程图 本系统程序的编写采用KEIL软件进行程序的编写,用USB ISP程序下载器将编写好的程序烧写入STC89C52单片机,软件界面如下图 程序流程图五测试方案与测试条件 5.1测试方案 将飞行器放在圆形区域A或B,让单片机自主控制飞行器飞行,观察飞行器的飞行高度与飞行方向和时间,若飞行器不能按预定的方案飞行就调整程序的PID参数再进行测试。 5.2测试条件 飞行器应该在水平的地面上起飞,0605芯片不能倾斜。场地应有黑线作为指示线引导飞行器前进 六 结论1、由于对PID算法不够了解,导致不能够用无刷电调控制电机转动, 2、原理图命名严禁重复,同一类器件最好按功能模块的不同明显的加以区分,例如模块1中的电阻命名为R101,R102,模块2中的电阻命名为R201,R202,以此类推;在原理图中制作Library元件时,在放置引脚时,末端的黑色小圆圈一定要朝外,否则将无连接;原理图中的标号一定要正确放置在引脚或连线上,有时看上去连在一起了,其实并未连上;画原理图电气线时,导线要用Place wire,而非Drawing Tools,不然在PCB设计中,装入元件后发现无飞线,在ERC检查及装入网表时并未报错;用电容滤除噪声信号,达到去耦效果。每10片左右IC要加一片充放电电容或蓄能电容,可选10uF左右,使用钽电容或聚碳酸酯电容,最好不要电解电容。去耦电容的选用不严格,可按C=1F标准选取,即10MHz取O1uF,100MHz取001uF;贴片零件的引脚不能当过孔使用,千万把下层的线连到上层芯片的引脚上(Protel 99显示可连接),反之相同。3、围绕着飞行控制系统的硬件设计要求,我们研究并制作了四旋翼飞行器控制系统的硬件电路。了解到了系统主要模块的硬件设计包括模块的器件选型和设计方法,包括传感器模块、四电机控制模块、无线通信模块和电源模块,最后还了解到了PCB排版布局和抗干扰的措施。附录附录一:元器件明细表 1 STC89C52单片机 2 直流吸盘式电磁铁3 红外传感器4 超声波传感器5新西达A2212无刷电机6新西达A2212无刷电调7 LCD1602显示器附录二:仪器设备清单 1 线性稳压电源2 数字示波器 附录三:源程序 MPU6050程序/*/ Update to MPU6050 by shinetop/ MCU: STC89C52/ 2012.3.1/ 功能: 显示加速度计和陀螺仪的10位原始数据/*/ GY-52 MPU3050 IIC测试程序/ 使用单片机STC89C51 / 晶振:11.0592M/ 显示:LCD1602/ 编译环境 Keil uVision2/ 参考宏晶网站24c04通信程序/ 时间:2011年9月1日/ QQ:/*#include <REG52.H>#include <math.h> /Keil library #include <stdio.h> /Keil library#include <INTRINS.H>typedef unsigned char uchar;typedef unsigned short ushort;typedef unsigned int uint;/*/ 定义51单片机端口/*#define DataPort P0/LCD1602数据端口sbit SCL=P10;/IIC时钟引脚定义sbit SDA=P11;/IIC数据引脚定义sbit LCM_RS=P20;/LCD1602命令端口sbit LCM_RW=P21;/LCD1602命令端口sbit LCM_EN=P22;/LCD1602命令端口 /*/ 定义MPU6050内部地址/*#defineSMPLRT_DIV0x19/陀螺仪采样率,典型值:0x07(125Hz)#defineCONFIG0x1A/低通滤波频率,典型值:0x06(5Hz)#defineGYRO_CONFIG0x1B/陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)#defineACCEL_CONFIG0x1C/加速计自检、测量范围及高通滤波频率,典型值:0x01(不自检,2G,5Hz)#defineACCEL_XOUT_H0x3B#defineACCEL_XOUT_L0x3C#defineACCEL_YOUT_H0x3D#defineACCEL_YOUT_L0x3E#defineACCEL_ZOUT_H0x3F#defineACCEL_ZOUT_L0x40#defineTEMP_OUT_H0x41#defineTEMP_OUT_L0x42#defineGYRO_XOUT_H0x43#defineGYRO_XOUT_L0x44#defineGYRO_YOUT_H0x45#defineGYRO_YOUT_L0x46#defineGYRO_ZOUT_H0x47#defineGYRO_ZOUT_L0x48#definePWR_MGMT_10x6B/电源管理,典型值:0x00(正常启用)#defineWHO_AM_I0x75/IIC地址寄存器(默认数值0x68,只读)#defineSlaveAddress0xD0/IIC写入时的地址字节数据,+1为读取/*/定义类型及变量/*uchar dis4;/显示数字(-511至512)的字符数组intdis_data;/变量/intTemperature,Temp_h,Temp_l;/温度及高低位数据/*/函数声明/*void delay(unsigned int k);/延时/LCD相关函数void InitLcd();/初始化lcd1602void lcd_printf(uchar *s,int temp_data);void WriteDataLCM(uchar dataW);/LCD数据void WriteCommandLCM(uchar CMD,uchar Attribc);/LCD指令void DisplayOneChar(uchar X,uchar Y,uchar DData);/显示一个字符void DisplayListChar(uchar X,uchar Y,uchar *DData,L);/显示字符串/MPU6050操作函数void InitMPU6050();/初始化MPU6050void Delay5us();void I2C_Start();void I2C_Stop();void I2C_SendACK(bit ack);bit I2C_RecvACK();void I2C_SendByte(uchar dat);uchar I2C_RecvByte();void I2C_ReadPage();void I2C_WritePage();void display_ACCEL_x();void display_ACCEL_y();void display_ACCEL_z();uchar Single_ReadI2C(uchar REG_Address);/读取I2C数据void Single_WriteI2C(uchar REG_Address,uchar REG_data);/向I2C写入数据/*/整数转字符串/*void lcd_printf(uchar *s,int temp_data)if(temp_data<0)temp_data=-temp_data;*s='-'else *s=' '*+s =temp_data/100+0x30;temp_data=temp_data%100; /取余运算*+s =temp_data/10+0x30;temp_data=temp_data%10; /取余运算*+s =temp_data+0x30; /*/延时/*void delay(unsigned int k)unsigned int i,j;for(i=0;i<k;i+)for(j=0;j<121;j+);/*/LCD1602初始化/*void InitLcd()WriteCommandLCM(0x38,1);WriteCommandLCM(0x08,1);WriteCommandLCM(0x01,1);WriteCommandLCM(0x06,1);WriteCommandLCM(0x0c,1);DisplayOneChar(0,0,'A');DisplayOneChar(0,1,'G');/*/LCD1602写允许/*void WaitForEnable(void)DataPort=0xff;LCM_RS=0;LCM_RW=1;_nop_();LCM_EN=1;_nop_();_nop_();while(DataPort&0x80);LCM_EN=0;/*/LCD1602写入命令/*void WriteCommandLCM(uchar CMD,uchar Attribc)if(Attribc)WaitForEnable();LCM_RS=0;LCM_RW=0;_nop_();DataPort=CMD;_nop_();LCM_EN=1;_nop_();_nop_();LCM_EN=0;/*/LCD1602写入数据/*void WriteDataLCM(uchar dataW)WaitForEnable();LCM_RS=1;LCM_RW=0;_nop_();DataPort=dataW;_nop_();LCM_EN=1;_nop_();_nop_();LCM_EN=0;/*/LCD1602写入一个字符/*void DisplayOneChar(uchar X,uchar Y,uchar DData)Y&=1;X&=15;if(Y)X|=0x40;X|=0x80;WriteCommandLCM(X,0);WriteDataLCM(DData);/*/LCD1602显示字符串/*void DisplayListChar(uchar X,uchar Y,uchar *DData,L)uchar ListLength=0; Y&=0x1; X&=0xF; while(L-) DisplayOneChar(X,Y,DDataListLength);ListLength+; X+; /*/延时5微秒(STC90C52RC12M)/不同的工作环境,需要调整此函数/当改用1T的MCU时,请调整此延时函数/*void Delay5us()_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();/*/I2C起始信号/*void I2C_Start() SDA = 1; /拉高数据线 SCL = 1; /拉高时钟线 Delay5us(); /延时 SDA = 0; /产生下降沿 Delay5us(); /延时 SCL = 0; /拉低时钟线/*/I2C停止信号/*void I2C_Stop() SDA = 0; /拉低数据线 SCL = 1; /拉高时钟线 Delay5us(); /延时 SDA = 1; /产生上升沿 Delay5us(); /延时/*/I2C发送应答信号/入口参数:ack (0:ACK 1:NAK)/*void I2C_SendACK(bit ack) SDA = ack; /写应答信号 SCL = 1; /拉高时钟线 Delay5us(); /延时 SCL = 0; /拉低时钟线 Delay5us(); /延时/*/I2C接收应答信号/*bit I2C_RecvACK() SCL = 1; /拉高时钟线 Delay5us(); /延时 CY = SDA; /读应答信号 SCL = 0; /拉低时钟线 Delay5us(); /延时 return CY;/*/向I2C总线发送一个字节数据/*void I2C_SendByte(uchar dat) uchar i; for (i=0; i<8; i+) /8位计数器 dat <<= 1; /移出数据的最高位 SDA = CY; /送数据口 SCL = 1; /拉高时钟线 Delay5us(); /延时 SCL = 0; /拉低时钟线 Delay5us(); /延时 I2C_RecvACK();/*/从I2C总线接收一个字节数据/*uchar I2C_RecvByte() uchar i; uchar dat = 0; SDA = 1; /使能内部上拉,准备读取数据, for (i=0; i<8; i+) /8位计数器 dat <<= 1; SCL = 1; /拉高时钟线 Delay5us(); /延时 dat |= SDA; /读数据 SCL = 0; /拉低时钟线 Delay5us(); /延时 return dat;/*/向I2C设备写入一个字节数据/*void Single_WriteI2C(uchar REG_Address,uchar REG_data) I2C_Start(); /起始信号 I2C_SendByte(SlaveAddress); /发送设备地址+写信号 I2C_SendByte(REG_Address); /内部寄存器地址, I2C_SendByte(REG_data); /内部寄存器数据, I2C_Stop(); /发送停止信号/*/从I2C设备读取一个字节数据/*uchar Single_ReadI2C(uchar REG_Address)uchar REG_data;I2C_Start(); /起始信号I2C_SendByte(SlaveAddress); /发送设备地址+写信号I2C_SendByte(REG_Address); /发送存储单元地址,从0开始I2C_Start(); /起始信号I2C_SendByte(SlaveAddress+1); /发送设备地址+读信号REG_data=I2C_RecvByte(); /读出寄存器数据I2C_SendACK(1); /接收应答信号I2C_Stop(); /停止信号return REG_data;/*/初始化MPU6050/*void InitMPU6050()Single_WriteI2C(PWR_MGMT_1, 0x00);/解除休眠状态Single_WriteI2C(SMPLRT_DIV, 0x07);Single_WriteI2C(CONFIG, 0x06);Single_WriteI2C(GYRO_CONFIG, 0x18);Single_WriteI2C(ACCEL_CONFIG, 0x01);/*/合成数据/*int GetData(uchar REG_Address)char H,L;H=Single_ReadI2C(REG_Address);L=Single_ReadI2C(REG_Address+1);return (H<<8)+L; /合成数据/*/在1602上显示10位数据/*void Display10BitData(int value,uchar x,uchar y)value/=64;/转换为10位数据lcd_printf(dis, value);/转换数据显示DisplayListChar(x,y,dis,4);/启始列,行,显示数组,显示长度/*/显示温度/*/void display_temp()/ /Temp_h=Single_ReadI2C(TEMP_OUT_H); /读取温度/Temp_l=Single_ReadI2C(TEMP_OUT_L); /读取温度/Temperature=Temp_h<<8|Temp_l; /合成温度/Temperature = 35+ (double) (Temperature + 13200) / 280; / 计算出温度/lcd_printf(dis,Temperature); /转换数据显示/DisplayListChar(11,1,dis,4); /启始列,行,显示数组,显示位数/*/主程序/*void main() delay(500);/上电延时InitLcd();/液晶初始化InitMPU6050();/初始化MPU6050delay(150);while(1)Display10BitData(GetData(ACCEL_XOUT_H),2,0);/显示X轴加速度Display10BitData(GetData(ACCEL_YOUT_H),7,0);/显示Y轴加速度Display10BitData(GetData(ACCEL_ZOUT_H),12,0);/显示Z轴加速度Display10BitData(GetData(GYRO_XOUT_H),2,1);/显示X轴角速度Display10BitData(GetData(GYRO_YOUT_H),7,1);/显示Y轴角速度Display10BitData(GetData(GYRO_ZOUT_H),12,1);/显示Z轴角速度delay(500);专心-专注-专业
展开阅读全文