LCR技术报告Word文档下载推荐.docx
《LCR技术报告Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《LCR技术报告Word文档下载推荐.docx(69页珍藏版)》请在冰点文库上搜索。
系统电路部分需要包括单片机控制单元、电机驱动电路、陀螺仪与加速度计电路、线性CCD电路等部分,除此之外系统还需要一些外部设备,例如编码器测速、直流电机驱动车体和控制车体方向。
综上所述,本智能车系统包含了以下几个模块:
1.电源模块
2.单片机最小系统模块
3.传感器模块
4.电机模块
5.陀螺仪与加速度计模块
6.测速模块
7.人机交互模块
系统的整体模块如图1.2.1所示:
图1.2.1系统框架图
第二章智能车机械结构调整与优化
2.1智能车参数要求
1.传感器数量要求:
传感器数量不超过16个:
光电传感器接受单元计为1个传感器,发射单元不计算;
CCD传感器计为1个传感器;
2.电机型号:
RN260-CN-2875
3.全部电容容量和不得超过2000微法;
电容最高充电电压不得超过25伏。
2.2智能车整体参数调校
智能车的整体参数,包括车体重心、高度、传感器排布方式等,都对整个智能车系统的稳定运行起着至关重要的作用。
因此,对智能车机械系统的调节,有助于小车更快更稳定的运行。
小车的布局以精简、可靠、稳定为前提,通过对小车的布局,尽量保证小车左右平衡,以及寻找一个合适的重心,保证小车既能稳定快速前进,又能在转弯时流畅。
光电组车模如图2.2.1所示
图2.2.1车模示意图
车模运行状态如图2.2.2所示
图2.2.2车模示意图
车模整体外观如图2.2.3所示
图2.2.3车模整体外观
2.3编码器安装
选用可以5V工作电压的512线MINI光电编码器进行速度的测量,保证测量的精度。
速度传感器用螺钉通过支架固定在后轮支架上,这样固定好之后,就有了较高的稳定性。
然后调节编码器齿轮,使其与差速齿轮紧密咬合,增大测速的精确性,但是咬合过紧也增大了摩擦,减小了对电机做功的利用率,影响小车的快速行驶,因此减小摩擦同时增强齿轮间的咬合是我们主要考虑的因素。
用齿轮润滑油涂抹齿轮有不错效果。
编码器安装示意图如图2.4.1所示:
图2.3.1编码器安装示意图
2.4陀螺仪与加速度传感器安装
本次设计中陀螺仪采用的是村田公司的ENC-03系列的陀螺仪。
智能车在行进过程中,车体仅绕两后轮的轴心线做转动。
芯片外观是长方形的,安装时,应注意将长的一边与后轮轴心线平行。
此外,还应注意的是,陀螺仪的输出受温度的影响比较大,为避免环境温度变化对输出的影响,我们将陀螺仪和加速度计作为一个单独的模块,采用FFC线与主板连接,安装在车身的背面。
与陀螺仪一样,加速度传感器的性能与安放位置也有很大的关系。
加速度传感器是根据其XYZ轴上的模拟输出电压来确定车身的倾角。
由于我们测量的倾角只有一个,所以可以使用Z轴的输出来计算,当小车倾角为0时,Z轴对应的面应该处于水平。
图2.4.1ENC-03陀螺仪与加速度计
转直立陀螺仪位置不水平会造成弯加减速。
而事实上即便在安装传感器时非常小心,但陀螺仪芯片和陀螺仪电路板、陀螺仪电路板和主板、主板和车轮之间都有位置误差,累计起来你的陀螺仪还是可能不平,我们使用了如下测试陀螺仪倾斜程度的方法。
将车身放置在一个推力轴承上,让车体在上面转动,读取陀螺仪返回的数据。
用这种方法矫正陀螺仪方便有效,如图2.4.2所示。
图2.4.2推力轴承
第三章硬件电路设计说明
本智能车硬件系统以稳定为设计的原则,在有限的条件下做到最好。
单片机采用MC9S12XS128。
使用LM2940-5为各个模块供电,电机驱动使用芯片BTS7970。
调试过程中,采用OLED、蓝牙等模块辅助,方便小车的调试。
本章均有详细介绍。
3.1单片机最小系统模块
以MC9S12XS128为核心的单片机最小系统是本智能车的核心。
图3.1.1主板电路
3.2传感器模块
线性CCD是光电组小车最重要的模块之一,能够分辨白色的赛道及黑色的边线,对道路状况的检测起着至关重要的作用。
TSL1401线性CCD传感器包含128个线性排列的光电二极管。
每个光电二极管都有各自的积分电路,以下我们将此电路统称为像素。
每个像素所采集的图像灰度值与它所感知的光强和积分时间成正比。
一般来说线性CCD模块的焦距是固定的,因此要想得到清晰的图像就需要通过调节镜头的进出来解决。
如果镜头拧的位置合适,则会得到清晰的图像,CCD输出的数据在波形上会表现的比较尖锐,如图3.2.1所示。
图3.2.1
图3.2.3传感器排布方案
3.3电机模块
电机采用芯片BTS7970,其应用非常简单,只需要向芯片第2引脚输入PWM波就能控制。
当系统中只需要单向控制时,只需要让电机一端接地,另一端接BTS7960第4引脚。
如果需要电机双向旋转控制,则需要另一片BTS7960共同组成全桥。
由于小车使用双电机,所以我们使用4片BTS7970构成两个全桥分别控制两个电机。
图3.3.1电机驱动电路
3.4测速模块
本小车使用512线的光电编码器进行小车的测速,以保证测量精度,并且直接有方向输出,使用方便。
LM2940-5为其提供5V工作电压。
由于MC9S12XS128只有一个脉冲计数器,我们采用分时复用的方式对左右两轮计数。
图3.4.1多路选择器电路
3.5陀螺仪与加速度计模块
我们采用AMS1117为陀螺仪(ENC-03MB)和加速度计(MMA7361)提供3.3V的工作电压。
由于陀螺仪数据手册上的输出有过冲,不利于积分,我们采用官方提供的电路。
3.5.1陀螺仪电路
3.5.2加速度计电路
3.6人机交互模块
为了方便调试,本车有蓝牙模块,有效进行运行参数之间的传送,除此之外,还设置了键盘、液晶显示屏,以方便控制参数的修改和智能车的调试。
第四章智能车控制软件设计说明
4.1MC9S12XS128片资源简介
MC9S12XS128微控制单元作为MC9S12系列的16位单片机,由标准片上外围设备组成,包括16位中央处理器、128KB的Flash存储器、8KB的RAM、2KB的EEPROM、两个异步串行通信接口、两个串行外围接口、一组8通道的输入捕捉或输出捕捉的增强型捕捉定时器、两组8通道10路模数转换器、一组8通道脉宽调制模块、一个字节数据链路控制器、29路独立的数字I/O接口、20路带中断和唤醒功能的数字I/O接口、5个增强型CAN总线接口。
同时,单片机内的锁相环电路可使能耗和性能适应具体操作的需要。
MC9S12XS128片内资源表如图5.1:
图4.1MC9S12XS128片内资源
4.2MC9S12XS128所用模块简介
在整个系统设计中,用到了5个单片机基本功能模块:
时钟模块、PWM输出模块、ECT模块、串口通信模块以及普通IO模块。
根据系统实际需求,对各个模块进行了初始化配置,通过对相应数据寄存器或状态寄存器的读写,实现相应的功能。
4.2.1时钟模块
XS12单片机中有四个不同的时钟,即外部晶振时钟、锁相环时钟、总线时钟和内核时钟。
当前电路板采用的是16MHz的有源晶振,因此外部晶振时钟为16MHz;
默认设置下,锁相环时钟为80MHz,总线时钟为40MHz,内核时钟为16MHz。
锁相环时钟与外部晶振时钟的倍、分频关系由SYNR、REFDV两寄存器决定。
总线时钟用作片上外围设备的同步,而内核时钟则用作CPU的同步,它决定了指令执行的速度。
时钟模块初始化程序如下:
voidPll_Init(void)
{
CLKSEL=0x00;
//disengagePLLtosystem
PLLCTL_PLLON=1;
//turnonPLL
SYNR=0x53;
//注意VCOFRQ[7:
6];
SYNDIV[5:
0];
fVCO=2*fOSC*(SYNDIV+1)/(REFDIV+1);
fPLL=fVCO/(2×
POSTDIV);
BUS=fPLL/2
REFDV=0x07;
//REFFRQ[7:
REFDIV[5:
0]
POSTDIV=0x00;
_asm(nop);
while(!
(CRGFLG_LOCK==1));
//whenpllissteady,thenuseit;
CLKSEL_PLLSEL=1;
//engagePLLtosystem;
}
4.2.2PWM模块
脉宽调制模块有8路独立的可设置周期和占空比的8位PWM通道,每个通道配有专门的计数器。
该模块有4个时钟源,能分别控制8路信号。
通过配置寄存器可设置PWM的使能与否、每个通道的工作脉冲极性、每个通道输出的对齐方式、时钟源以及使用方式(八个8位通道还是四个16位通道)。
PWM模块的初始化设置过程为:
voidPWM_Init(void)
PWME=0x00;
//输出通道使能位。
1可对外输出波形;
0不能对外输出波形。
设置之前先禁止PWM[2567]
PWMPOL=0xff;
//通道对外输出波形先是高电平然后再变为低电平
PWMCLK=0xff;
//用clock_A,clock_B
PWMCAE=0x00;
//0为左对齐输出;
1为居中对其输出。
只有输出通道关闭情况下才可设置。
PWMCTL=0x00;
//把PWM不级联
//PWMPRCLK=0x33;
//时钟预分频,时钟A和B与分频结果CLKA=CLKB=E=5M.
//PWMPRCLK[0-7]PCKA[012]PCKB[456]
//CLKA=Busclock/(2^PCKA)CLKB=Busclock/(2^PCKB)
//CLKA=40M/(2^3)=5MCLKB=5M
PWMPRCLK=0x00;
PWMSCLB=8;
PWMSCLA=8;
PWMPER0=250;
PWMPER2=250;
PWMPER4=250;
PWMPER7=250;
PWMDTY0=0;
//初始时电机占空比为0,即电机转速为0.
//占空比=PWMDTYx/PWMPERx
PWMDTY2=0;
PWMDTY4=0;
PWMDTY7=0;
PWME=0xb5;
//PWM使能
4.3软件功能与框架
软件的主要功能包括有:
(1)各传感器信号的采集、处理;
(2)电机PWM输出;
(3)车模运行控制:
直立控制、速度控制、方向控制;
(4)车模运行流程控制:
程序初始化、车模启动与结束、车模状态监控;
(5)车模信息显示与参数设定:
状态显示、上位机监控、参数设定等。
图4.3.1主程序框架
程序上电运行后,便进行单片机的初始化。
初始化的工作包括有两部分,一部分是对于单片机各个应用到的模块进行初始化。
第二部分是应用程序初始化,是对于车模控制程序中应用到的变量值进行初始化。
初始化完成后,首先进入车模直立检测子程序。
该程序通过读取加速度计的数值判断车模是否处于直立状态。
如果一旦处于直立状态则启动车模直立控制、方向控制以及速度控制。
车模的直立控制、速度控制以及方向控制都是在中断程序中完成。
通过全局标志变量确定是否进行这些闭环控制。
中断程序框图如图4.3.2所示。
图4.3.2中断服务程序
图4.3.2中,使用定时器,产生一毫秒的周期中断。
中断服务程序的任务被均匀分配在0-4的中断片段中。
因此每个中断片段中的任务执行的周期为5毫秒,频率为200Hz。
将任务分配到不同的中断片段中,一方面防止这些任务累积执行时间超过1毫秒,扰乱一毫秒中断的时序,同时也考虑到这些任务之间的时间先后顺序。
这些任务包括:
(1)电机测速脉冲计数器读取与清除。
累积电机转动角度。
累积电机速度,为后面车模速度控制提供平均数;
(2)启动AD转换。
进行20次模拟量采集,然后计算各个通道的模拟量的平均值。
这个过程是对于模拟信号进行低通滤波。
(3)车模直立控制过程。
包括车模角度计算、直立控制计算、电机PWM输出等。
(4)车模速度控制:
在这个时间片段中,又进行0-19计数。
在其中第0片段中,进行速度PID调节。
因此,速度调节的周期为100毫秒。
也就是每秒钟调节10次。
(5)车模方向控制:
根据前面读取的电磁场检波数值,计算偏差数值。
然后计算电机差模控制电压数值。
4.4控制算法与函数
4.4.1直立控制程序设计
平衡控制算法最重要的是滤波算法和控制算法。
这里滤波的主要作用是使用加速度计滤除陀螺仪的漂移,也可以说是将加速度计和陀螺仪的数据融合。
其中滤波算法有卡尔曼滤波,官方的互补滤波,不滤波。
控制算法有PID和LQR线性二次型调节器。
卡尔曼滤波因为过于复杂而没有使用,官方互补滤波和卡尔曼滤波效果相似而且简单,不滤波动态效果最好但是无法消除陀螺仪累积误差。
最终我们选用了官方互补滤波,因为陀螺仪数据必须是最重要的。
将车模角度和角速度乘以各自相应的系数就可以得到直立控制输出量[4]
图4.4.1直立控制算法框图
voidAngleCalculate(void){
floatfDeltaValue;
intnGyro_Angle,nGravityAngle;
UINT8Gyro_Angle_H,Gyro_Angle_L,GravityAngle_H,GravityAngle_L;
UINT8Gyro_H,Gyro_L;
g_fGravityAngle=g_nCarAcceVal*Rz;
g_fGyroscopeAngleSpeed=g_nCarGyroVal*Rgyro;
//角速度单位转化g_fCarAngle=g_fGyroscopeAngleIntegral;
g_nCarAngle=(int)(g_fCarAngle/Rz);
fDeltaValue=(g_fGravityAngle-g_fCarAngle)/Tz;
g_fAngleDeltaValue=fDeltaValue;
g_fGyroscopeAngleIntegral+=(g_fGyroscopeAngleSpeed+fDeltaValue);
//nGravityAngle=(int)(g_fGravityAngle*100);
//GravityAngle_H=(byte)((nGravityAngle&
0xff00)>
>
8);
//GravityAngle_L=(byte)(nGravityAngle&
0x00ff);
//send_buf[5]=GravityAngle_H;
//send_buf[6]=GravityAngle_L;
//GYROSCOPE_ANGLE_SIGMA_FREQUENCY;
//nGyro_Angle=(int)(g_fCarAngle*100);
//Gyro_Angle_H=(byte)((nGyro_Angle&
//Gyro_Angle_L=(byte)(nGyro_Angle&
//send_buf[3]=Gyro_Angle_H;
//send_buf[4]=Gyro_Angle_L;
//Gyro_H=(byte)(((g_nCarGyroVal)&
//Gyro_L=(byte)(g_nCarGyroVal&
//send_buf[7]=Gyro_H;
//send_buf[8]=Gyro_L;
voidAngleControl(void){
floatfValue;
UINT8AngleControl_H,AngleControl_L;
intnAngleControl;
g_fCarSpeedSet=g_fSpeedControlOut;
fValue=g_fGyroscopeAngleSpeed*AngleDgainTemp*0.1+(g_fCarAngle)*AnglePgainTemp
g_fAngleControlOut=fValue;
//nAngleControl=(int)(g_fAngleControlOut*100);
//AngleControl_H=(byte)((nAngleControl&
//AngleControl_L=(byte)(nAngleControl&
//send_buf[9]=AngleControl_H;
//send_buf[10]=AngleControl_L;
}
4.4.2速度控制程序设计
为了使得速度具有一定的物理含义,对于所取得的电机速度值需要进行单位转换。
根据定义单位的物理含义,可以确定速度单位转换的比例值。
图4.4.2速度控制算法框图
voidSpeedControl(void){
floatfDelta,fCarSpeedReal;
floatfP,fI;
UINT8fCarSpeed_H,fCarSpeed_L,fCarSpeedReal_H,fCarSpeedReal_L,
fSpeedControlIntegral_H,fSpeedControlIntegral_L;
intnfCarSpeed,nfCarSpeedReal,nSpeedControlIntegral;
fCarSpeed=(g_nSpeedLeftCe+g_nSpeedRightCe)/2;
fCarSpeedReal=(g_fSpeedAveRight+g_fSpeedAveLeft)*0.5;
fCarSpeed=fCarSpeed_old*0.6+(g_fSpeedAveRight+g_fSpeedAveLeft)*0.2;
g_fCarSpeed=fCarSpeed*CAR_SPEED_CONSTANT;
fDelta=g_fSpeedGet-g_fCarSpeed;
fP=fDelta*SpeedPgain;
fI=fDelta*SpeedIgain;
if(g_fSpeedControlIntegral>
=3)//8))
{
if(fDelta<
0)
{
g_fSpeedControlIntegral+=fI;
;
}
elseif(g_fSpeedControlIntegral<
=-5)//-15))
if(fDelta>
g_fSpeedControlIntegral+=fI;
}else{
g_fSpeedControlIntegral+=fI;
}
fCarSpeed_old=fCarSpeed;
//nfCarSpeedReal=(int)(fCarSpeedReal);
//fCarSpeedReal_H=(byte)((nfCarSpeedReal&
//fCarSpeedReal_L=(byte)(nfCarSpeedReal&
//send_buf[3]=fCarSpeedReal_H;
//send_buf[4]=fCarSpeedReal_L;
//nfCarSpeed=(int)(fCarSpeed);
//fCarSpeed_H=(byte)((nfCarSpeed&
//fCarSpeed_L=(byte)(nfCarSpeed&
//send_buf[5]=fCarSpeed_H;
//send_buf[6]=fCarSpeed_L;
//nSpeedControlIntegral=(int)(g_fSpeedControlIntegral*10);
//fSpeedControlIntegral_H=(byte)((nSpeedControlIntegral&
//fSpeedControlIntegral_L=(byte)(nSpeedControlIntegral&
//send_buf[7]=fSpeedControlIntegral_H;
//send_buf[8]=fSpeedControlIntegral_L;
//缓冲函数
voidSpeedControlOutput(void){
UINT8SuduControl_H,SuduControl_L;
intnSuduControl;
fValue=g_fSpeedControlOutNew-g_fSpeedControlOutOld;
g_fSpeedControlOut=fValue*g_nSp