信号发生器的时域分析及球杆定位控制实验.docx
《信号发生器的时域分析及球杆定位控制实验.docx》由会员分享,可在线阅读,更多相关《信号发生器的时域分析及球杆定位控制实验.docx(23页珍藏版)》请在冰豆网上搜索。
信号发生器的时域分析及球杆定位控制实验
工程控制综合实验
部分一:
测试部分-----------------------2
部分二:
控制部分-----------------------22
综合实验总结---------------------------37
小组成员:
分工情况:
实验过程:
报告部分:
实验最终总结:
页面排版及目录:
部分一:
信号发生器的时域分析
一、时域分析的概念
时域分析是指控制系统在一定的输入下,根据输出量的时域表达式,分析系统的稳定性、瞬态和稳态性能。
由于时域分析是直接在时间域中对系统进行分析的方法,所以时域分析具有直观和准确的优点。
系统输出量的时域表示可由微分方程得到,也可由传递函数得到。
在初值为零时,一般都利用传递函数进行研究,用传递函数间接的评价系统的性能指标。
具体是根据闭环系统传递函数的极点和零点来分析系统的性能。
此时也称为复频域分析。
二、什么是Simulink?
Simulink是MATLAB提供的实现动态系统建模和仿真的一个软件包.它让用户把精力从编程转向模型的构造.Simulink一个很大的优点是为用户省去了许多重复的代码编写工作.
Simulink的启动。
首先须确定MATLAB已安装了Simulink工具箱.在工具栏点击Simulink图标:
或在CommandWindow中输入
>>Simulink
即出现SimulinkLibraryBrowser窗口:
Simulink从中可看到Simulink基本模块库及其子库,如Continuous,Discrete,…,Sinks,Sources等等.子库Sources(信源)中存放了各种信号源,如Clock(输出时间t),Constant(输出常数),SineWave(输出正弦波),Step(输出阶梯波)等等.
子库Sinks(信宿)中存放对数据的处理装置,如Display(显示数据),Scope(示波器),XYGraph(用图形显示两变量的函数关系),ToFile(存储到文件),ToWorkspace(存储到Workspace),StopSimulation(停止模拟)等等.
子库Continuous和Discrete分别存放连续离散的函数,如连续函数有Derivative(求导),Integrator(积分器),State-Space(状态空间),TransferFcn(传递函数)等等,离散的DiscreteTransferFcn(离散传递函数),DiscreteFilter(离散滤波器),DiscreteState-Space(离散状态空间)等等.在SimulinkLibraryBrowser窗口中,建立一个新模型(newmodel),即打开一个新的空白模型窗口,用鼠标左键点取所需要的模块拖到模型窗口中,用鼠标左键在模块间建立连接线(若在已有连接线上分叉则用右键)即可。
三、数据采集程序设计
S-Function
概念:
S-Function(Systemfunction)是simulink模块的计算机语言描述。
可以用M、C/C++、Ada、Fortan语言以MEX(可执行文件,再windows系统中就是其为dll文件)的形式编写。
S-Function以特殊的方式与simulink方程求解互交。
这种互交和simulink内建模块的做法非常相似。
S-Function模块可以是连续、离散或者混合系统。
通过S-Function,用户可以将自己的模块加入simulink模型中。
从而可以实现用户定义的算法或者与硬件设备交互等。
S-Function的工作机制
m文件s-function可用的子函数说明如下:
mdlInitializeSizes:
定义s-function模块的基本特性,包括采样时间、连续或者离散状态的初始条件和sizes数组。
mdlDerivatives:
计算连续状态变量的微分方程。
mdlUpdate:
更新离散状态、采样时间和主时间步的要求。
mdlOutputs:
计算s-function的输出。
mdlGetTimeOfNextVarHit:
计算下一个采样点的绝对时间,这个方法仅仅是在用户在mdlInitializeSizes里说明了一个可变的离散采样时间。
mdlTerminate:
实现仿真任务必须的结束。
概括说来,建立s-function可以分成两个分离的任务:
初始化模块特性包括输入输出信号的宽度,离散连续状态的初始条件和采样时间。
将算法放到合适的s-function子函数中去。
为了让Simulink识别出一个m文件s-function,用户必须在s-函数里提供有关s-函数的说明信息,包括采样时间、连续或者离散状态个数等初始条件。
这一部分主要是在mdlInitializeSizes子函数里完成。
Sizes数组是s-function函数信息的载体,它内部的字段意义为:
NumContStates:
连续状态的个数(状态向量连续部分的宽度)
NumDiscStates:
离散状态的个数(状态向量离散部分的宽度)
NumOutputs:
输出变量的个数(输出向量的宽度)
NumInputs:
输入变量的个数(输入向量的宽度)
DirFeedthrough:
有无直接馈入
NumSampleTimes:
采样时间的个数
S-function默认的4个输入参数为t、x、u和flag,它们的次序不能变动,代表的意义分别为:
t:
代表当前的仿真时间,这个输入参数通常用于决定下一个采样时刻,或者在多采样速率系统中,用来区分不同的采样时刻点,并据此进行不同的处理。
x:
表示状态向量,这个参数是必须的,甚至在系统中不存在状态时也是如此。
它具有很灵活的运用。
u:
表示输入向量。
flag:
是一个控制在每一个仿真阶段调用哪一个子函数的参数,由Simulink在调用时自动取值。
S-function默认的4个返回参数为sys、x0、str和ts,它们的次序不能变动,代表的意义分别为:
sys:
是一个通用的返回参数,它所返回值的意义取决于flag的值。
x0:
是初始的状态值(没有状态时是一个空矩阵[]),这个返回参数只在flag值为0时才有效,其他时候都会被忽略。
str:
这个参数没有什么意义,是MathWorks公司为将来的应用保留的,m文件s-function必须把它设为空矩阵。
ts:
是一个m×2的矩阵,它的两列分别表示采样时间间隔和偏移。
利用S-Function模版创建dll
1、新建一个文件夹——设置工作目录
2、打开matlab
3、生成S-function源文件
#defineS_FUNCTION_NAMElxy
4、生成动态链接库
5、在simulink窗口下,新建一个mdl文件,向其中添加一个S-function模块,双击模块将其中的S-function的name改为dll文件的名字。
6、添加常数项和toworkspace项
输入输出设置及采集编程
Lxy.cpp文件重要解释:
#defineS_FUNCTION_NAMElxy
#defineS_FUNCTION_LEVEL2
%将S_FUNCTION的名字和FUNCTION名字改为一致,这样生成一个基本的S_FUNCTIO的文件。
#include"simstruc.h"
#include"abc.h"
doublebuffer[5000];
doublebuffer1[5000];
intpnum;
charch[8];
%定义全局变量:
建立两个通道的数据缓存buffer,读取指数指针数和8通道2进制表示值
if(!
ssSetNumInputPorts(S,3))return;
ssSetInputPortWidth(S,0,1);
ssSetInputPortRequiredContiguous(S,0,true);
ssSetInputPortWidth(S,1,1);
ssSetInputPortRequiredContiguous(S,1,true);
ssSetInputPortWidth(S,2,1);
ssSetInputPortRequiredContiguous(S,2,true);ssSetInputPortDirectFeedThrough(S,0,1);
ssSetInputPortDirectFeedThrough(S,1,1);
ssSetInputPortDirectFeedThrough(S,2,1);
%设置3个输入通道,函数解释
VoidssSetNumInputPorts()函数第一个参数为模块的一个数据结构(一般不用改,值是s),第二个参数为设置有几个输入通道
VoidssSetInputPortWidth()函数第一个参数为模块的一个数据结构(一般不用改,值是s),第二个为接口的编号(从0开始,有几个端口就到几,比如3个输入端口就只能用0、1、2),第三个参数是第二个所指定的借口的宽度
VoidssSetInputPortDirectFeedThrough()函数第一个参数为模块的一个数据结构(一般不用改,值是s)第二个参数是借口的编号,第三个参数是用于指定借口的输入数据是否能在mdlOutputs或者mdlgettimeofnextvarhit中调用,0不是不能调用,1不是能调用,1表示能调用。
若两个输出的调整可按输入的调整方式进行
if(!
ssSetNumOutputPorts(S,1))return;
ssSetOutputPortWidth(S,0,1);
ssSetNumSampleTimes(S,1);
ssSetNumRWork(S,0);
ssSetNumIWork(S,0);
ssSetNumPWork(S,0);
ssSetNumModes(S,0);
ssSetNumNonsampledZCs(S,0);
%设置一个输出端口,函数说明
VoidssSetNumOutputPorts(S,1)函数第一个参数为模块的一个数据结构(一般不用改,值是s),第二个参数设置输出端口数。
doubleFs=u[0];//采样频率
if(ADCardInit()!
=1)//采集卡初始化
{
ssSetErrorStatus(S,"Can'tfindtheDAQCard!
");
}
DAQ1(0x10,Fs,1024*4,buffer);//开启采集Fs=5000
pnum=0;//初始化buf指针位置
}
函数解释:
ADCardInit()是采集卡dll函数,作用是初始化采集卡,作用是初始化采集卡。
如果初始化成功则返回1,用于判断是否连上采集卡。
DAQ1()函数为采集卡dll单通道采样函数,作用是采集卡进行单通道数据采集。
参数1为采样通道,是以8为2进制数表示各个通道是否打开。
我们选择的是通道5对应关系为0*10.
staticvoidmdlOutputs(SimStruct*S,int_Ttid)
{
intLength=1024*4;//读取的buffer长度
ReadDaq(5,Length,buffer);//从采集卡读取buffer
real_T*y=ssGetOutputPortRealSignal(S,0);//获取输出指针
if(pnum>=Length)pnum=0;//判断指针是否已满
*y=buffer[pnum];//输出第pnum个点的值
pnum++;//指针加1
}
%函数ReadDaq()作用事故读取下位机buf里的采样数据
参数1为通道号,分别为1~8
参数2为buffer长度;
参数3为保存的buffer指针。
GUI设计实验内容:
两个m文件
1、UI.m%负责设计界面的m文件
clfreset
set(gcf,'menubar','none')
set(gcf,'unit','normalized','position',[0.2,0.2,0.5,0.35]);
set(gcf,'defaultuicontrolunits','normalized');%设置用户缺省控件单位属性值
h_axes1=axes('position',[0.05,0.2,0.6,0.6]);
hpush1=uicontrol(gcf,'Style','push',...%制作“采集”按钮
'position',[0.8,0.25,0.18,0.15],'string','采集');
hpush2=uicontrol(gcf,'Style','push',...%制作“停止”按钮
'position',[0.8,0.05,0.18,0.15],'string','停止');
max_data=uicontrol(gcf,'Style','text',...
'position',[0.8,0.9,0.1,0.05],'string',maxa);%设置最大值数值的位置
texta=uicontrol(gcf,'Style','text',...
'position',[0.7,0.9,0.1,0.05],'string','峰值:
');%设置‘峰值’文本框位置
mean_data=uicontrol(gcf,'Style','text',...
'position',[0.8,0.8,0.1,0.05],'string',meana);%设置‘峰值’文本框位置
texta=uicontrol(gcf,'Style','text',...
'position',[0.7,0.8,0.1,0.05],'string','均值:
');%设置‘峰值’文本框位置
min_data=uicontrol(gcf,'Style','text',...
'position',[0.8,0.7,0.1,0.05],'string',peak);%设置peak数值文本框位置
texta=uicontrol(gcf,'Style','text',...
'position',[0.7,0.7,0.1,0.05],'string','峰峰值:
');%设置‘峰峰值’文本框位置
std_data=uicontrol(gcf,'Style','text',...
'position',[0.8,0.6,0.1,0.05],'string',stda);%设置均方差数值文本框位置
texta=uicontrol(gcf,'Style','text',...
'position',[0.7,0.6,0.1,0.05],'string','均方差:
');%设置‘均方差’文本框位置
sqrt_data=uicontrol(gcf,'Style','text',...
'position',[0.8,0.5,0.1,0.05],'string',ev);
texta=uicontrol(gcf,'Style','text',...
'position',[0.7,0.5,0.1,0.05],'string','有效值:
');%设置‘有效值’文本框位置
set(hpush1,'callback',[...
'set_param(''ypx'',''SimulationCommand'',''start''),',...'t=timer(''TimerFcn'',''getdata'',''Period'',2,''ExecutionMode'',''fixedSpacing'',''TasksToExecute'',inf),',...%设置定时器,运行getdata文件,与上面是一行。
'pause
(2);start(t);',...%暂停2秒并启动定时器
]);%“停止”按键引起的回调
%set(hpush1,'callback','getdata');
hpush2=uicontrol(gcf,'Style','push',...
'position',[0.8,0.05,0.18,0.15],'string','停止');%制作“停止”按钮
set(hpush2,'callback','stop(t);set_param(''ypx'',''SimulationCommand'',''stop'');');%停止定时器,mdl文件停止运行。
函数说明:
例如:
mean_data=uicontrol(gcf,'Style','text',...
'position',[0.8,0.8,0.1,0.05],'string',meana);
mean_data代表一个句柄的名称
uicontrol:
uicontrol 创建用户界面控件对象
gcf,'Style','text','position'都是其中的属性,其中
'text'——创建静态文本控件
2、Getdata.m文件%编程得到数据
set_param('ypx','SimulationCommand','stop');设置停止
yy=evalin('base','ydata.signals.values');%从mdl文件中取出信号
y1=yy(1:
800);
axes(h_axes1);%句柄
plot(y1);%画图
maxa=max(y1);%求峰值
mina=min(y1);%求最小值
peak=maxa-mina;%求峰峰值
meana=mean(y1);%求均值
ev=maxa*0.707;%求三角函数的有效值
set_param('ypx','SimulationCommand','start');
频率:
91.32Hz峰峰值7.7v
频率:
33.04Hz峰峰值2.5v
频率:
38.41Hz峰峰值2.5v
频率:
71.6Hz峰峰值8.1v
频率:
162.31Hz峰峰值7.7v
频率:
367.66Hz峰峰值2.2v
测试感想:
部分二:
球杆定位控制系统实验
整个球杆机构一共由以下几个部件组成:
连杆机构及其相应的电器驱动、传感部分等。
工作流程是通过电机驱动,带动连杆运动,改变球杆所在的滑到的倾斜角度,使钢球在重力的作用下沿着滑到运动。
本实验内容是详细的了解系统的结构,关键部件,并联机测试各个部件工作是否正常。
由机械建模可以得到实际上球杆系系统是一个二阶系统。
经过理论的数学分析和推到之后开始进行matlab的仿真实验,步骤大致可以列为:
1)连接球杆定位系统和电源线,通讯线以及电源箱。
2)接通电源打开测试软件,并运行matlab软件,在观察完QGTEST.MDL之后对速度,加速度,各个位置在scolp上面的显示之后开始自己的自主实验。
自主实验共有Move_Abs、Get_AD、stopandservo的创立。
其中Move_Abs是用来改变输入的常量,即曲柄的运动速度、加速度、最终停留位置的,Get_AD是用来采集小球在球杆上面的数据的,stopandservo是伺服控制,此次实验的目的是根据球杆系统的模型,建立使用PID控制器,控制球在球杆某位置的simulink控制模型,即在控制面板上面输入预期要求小球达到的位置,然后小球在球杆的控制下面达到指定的位置并且保持稳定的效果。
以下为我们组搭载的simulink界面,基本与已给出的QGTEST一致:
(1)Move_Abs界面:
(2)Get_AD界面:
(3)untitled/UnableSubsystem:
(4)untitled/UnableSubsystem/Subsystem:
以上为几个模块的制作界面,下面说明我们制作整个实验的经历和过程:
首先根据指导书上的过程,我们搭建了指定的Move_Abs、Get_AD、stopandservo,然后再在untitled/UnableSubsystem中创建五个输出的选项,分别为:
KpKiKdTU.
查阅机械工程控制基础方面的书籍中关于PID调节的内容,我们知道了PID调节器的控制作用有以下几点:
(1)比例系数Kp直接决定控制作用的强弱,加大Kp可以减少系统的稳态误差,提高系统的动态响应速度,但是Kp过大会使动态质量变坏,引起被控制量震荡甚至导致闭环系统不稳定。
(2)在比例调节的基础上加上积分控制可以消除系统的稳态误差,直到积分为零,控制作用才停止。
但是将使系统的动态过程变慢,而且过强的积分作用使系统的超调量增大,从而使系统的稳定性变坏。
(3)微分的控制作用是跟偏差的变化速度有关的。
微分控制能够预测偏差,产生超前的校正作用,有助于减少超调,克服振荡,使系统趋于稳定,并能加快系统的响应速度,减少调整时间,从而改善了系统的动态性能。
微分作用的不足之处是放大了噪声信号。
所以我们的目标就是尽可能的让KpKiKd较大,这样可以是信号的图像更加稳定。
实验过程中遇到的问题以及解决的办法:
实验的过程并不是很顺利,在一开始的时候甚至连球杆定位系统的调整支架都只能转动一圈,无论如调整untitled/UnableSubsystem中的KpKiKdTU五个参数都不能使出来的函数图象有任何的改变,一直都是只转动一圈然后就不停的抖动和微调,第一节课就在这样的过程中失败的度过。
第二节课的时候还是按照之前的办法,将matlab打开,然后打开先前保存过得文件夹,将里面的MDL文件都打开,结果发现之前的问题出在根本没有封装untitled/UnableSubsystem,所以里面的数据都无法运行,所以肯定电机无法正常的运转,这次封装之后又发现一个问题,就是在右键untitled/UnableSubsystem的lookundermask发现里面的3个gain上面显示的是具体的某一个数字,而不是应该有的"T"、“Kp”、“Kd/T”,这样导致的结果是外层的那几个KpKiKdTU的数据具体的设置是没有用的,因为输入的数据是无法被系统读取的,所以我们将子系统简图重新检查并且改良,之后确定封装之后就可以看到改变KpKiKdTU的某一参数之后图像会有明显的变化,在后面会截图展示我们对数据的调试的过程和图形的变化。
还有一个很愚蠢的问题,就是T的设置,我们开始的时候将T当做一个变量去设置,没出一组参数就改一个T变量。
但是后来才知道T=0.02.否则数据调不出来,所以绕了很多弯路,但是结果是好的,最终我们调处了理想的效果,而且精确度比较高。
附:
matlab界面数据调试和函数结果曲线图。
(1)Kp=20Ki=1Kd=5T=0.02U=1000ballsettingpos=100.
(2)Kp=20Ki=1Kd=5T=0.02U=1000ballsettingpos=200.
(3)Kp=20Ki=1Kd=5T=0.02U=1000ba