《机电控制系统仿真与软件设计》Word文档格式.docx
《《机电控制系统仿真与软件设计》Word文档格式.docx》由会员分享,可在线阅读,更多相关《《机电控制系统仿真与软件设计》Word文档格式.docx(25页珍藏版)》请在冰豆网上搜索。
1天
2
水塔水位控制系统SIMULINK建模仿真
3
控制代码的自动生成和修改、编译与仿真
4
仿真控制系统调试分析、编写设计报告
5
答辩
表1课程安排
四、MATLAB/Stateflow学习
通过MATLAB是一种科学计算软件,专门以矩阵的形式处理数据。
MATLAB将高性能的数值计算能力和强大的数字可视化功能集成在一起,提供了大量的内置函数,因而被广泛地应用于科学计算、控制系统、信息处理等领域的分析仿真和设计工作;
而Stateflow是集成于Simulink中的图形化设计与开发工具,主要用于针对控制系统中的复杂控制逻辑进行建模和仿真,即适用于对事件响应系统进行建模和仿真。
Stateflow和Simulink结合起来,可以创建确定性监管控制系统。
利用Stateflow可视化的模型和直观的仿真能力,可以清晰、简洁地反映出动态逻辑关系。
它的基础是有限状态机理论,它通过状态图、流程图的创建,对事件驱动系统进行建模和仿真。
此次课程设计是基于MATLAB/Stateflow软件上的一次实践,利用Stateflow可视化的模型和直观的仿真能力,对水塔进行逻辑图的绘制,建立动态系统模型进行仿真。
然后对仿真出来的代码进行修改和添加。
这样就不需要花太多时间从事代码的开发
,可以让设计者腾出更多的精力进行顶层控制策略的设计。
采用Stateflow
进行系统建模
,直观、逻辑关系清晰、简便
,RTW
生成执行代码正确
,可以大大缩短系统开发周期。
五、水位控制系统模型
首先在matlab2013a\simulink下建立起水塔水位控制模型如图2所示,并保存。
图2simulink下建立控制模型
In1、In2为控制输入端(P1.0口、P1.1口的按键输入),设定信号名称为delay,该信号作为stateflow中状态之间变换的转换条件(等效按键的按下产生的脉冲)。
Out1、Out2为模型的输出端。
(电机和指示灯的输出端口)
在stateflow菜单view下的ModelExplorer中设定输入、输出。
输入High_a,port为1,数据类型DataType为uit8,输入low_b,port为1,数据类型DataType为uit8,输入delay触发Trigger为Falling(因为单片机中,设置是按键按下时产生一个下降沿)。
输出为M、led,port分别为1、2,数据类型DataType为uit8如图所示。
图3ModelExplorer输入输出设定
Chart模块为stateflow模块,定义了High_a、Low_b两个输入变量、M、led两个输出端口。
图4stateflow建模
初始状态:
有4种不同的情况High_a和Low_b都为1;
High_a和Low_b都为0;
High_a为1,Low_b为0;
High_a为0,Low_b为1。
这4种状态将直接进入四种不同的固定状态,执行相应的命令。
四种固定状态:
(1)状态A为(工作状态):
水位在水位的下限Low_b下,输入信号High_a和Low_b都为1。
M(抽水电机工作状态),此时led=1(指示灯亮)。
(2)状态A1为(故障状态):
水位在水位的下限High_a以上,未到达水位上限Low_b。
,此时motor=0(电机停止),led闪烁(由子状态来实现)A4、A5状态间的转移以delay条件实现亮灭。
图5A1模型
(3)状态A2为(中间状态):
电机和指示灯都保持原来的运行状态不变。
(4)状态A3为(停机状态):
水位在水位的下限Low_b以上,也到达水位上限High_a。
M(抽水电机停止状态),此时led=0(指示灯灭)。
(5)delay
事件(delay为转移条件用fail(下降边沿触发)。
(6)状态1、状态2、状态3之间的转移条件为水位传感器
B、C
来决定。
(即由输入信号High_a和Low_b决定)当输入信号High_a和Low_b都为1,进入状态A执行命令。
完毕后进入中间状态A2,等待下一个输入信号(High_a和Low_b)的变化,再选择进入相应的状态执行命令。
图6状态及状态转换
设定好stateflow了以后,再设置simulink中的ConfigurationParameters,Solveroptions中Type选择定步长Fixed-step,其他默认;
硬件HardwareImplement选项Devicevendor选择Intel,Devicetype选择8051,其他默认;
Real-timeWorkshop中,Systemtargetfile选项选择ert.tlc,编译语言language选择C,其他默认。
然后在simulink菜单中Tools选择Real-timeWorkshop下的BuildModel,在matlab命令窗口commandwindow中可以看到详细的编译步骤,编译成功后,simulink文件所在文件夹会出现名为test_ert_rtw的文件夹,在该文件夹下,建立如图所示的proteus仿真模型,取名为test;
并建立名为test的keil新工程,芯片选择ATMEL公司的AT89C51,接下来要将rtw编译所得到的C源文件导入keil中修改并进行编译生成单片机可执行的.hex文件。
六、嵌入式C代码
描在simulink菜单中Tools选择Real-time
Workshop下的Build
Model,在matlab命令窗口command
window中可以看到详细的编译步骤,编译成功后,simulink文件所在文件夹会出现名为untitled_ert_rtw的文件夹。
在该文件夹下,建立如附录3所示的proteus仿真模型,取名为水塔电路图;
并建立名为untitled的keil新工程,芯片选择ATMEL公司的AT89C51,接下来要将rtw编译所得到的C源文件导入keil中修改并进行编译生成单片机可执行的.hex文件。
在keil工程中,Source
Group
1导入rtw编译所得到的C源文件,共有3个,一个为ert_main.c、一个为untitled.c还有rt_zcfcn.c,ert_main.c为主程序,里面要设定输入输出端口,untitled.c为功能程序。
图7导入C源文件
(1)如果不进行修改,直接编译会报错,不能编译通过。
主要是要修改ert_main.c文件,打开后在头文件处加入#include<
reg51.h>
,并对所到的管脚进行定义。
如图所示。
图8修改头文件和加入管脚定义
(2)接下来设定模型输入输出管脚,如图所示。
图9添加模型输入输出管脚
(3)其中输入输出管脚的名称,可以在test.c中查找得到,必须保持一致。
接下来,要对main函数进行修改。
改成
(4)将如下程序段屏蔽或者删除。
在while循环体中添加rt_OneStep();
即变成
将程序中的(void)(argc);
fflush((NULL));
程序段屏蔽如图所示。
(5)进行编译,会提示找不到solver_zc.h文件,解决办法为:
在matlab安装目录下,搜索查找solver_zc.h,将找到的这个文件,复制到test_ert_rtw的文件夹即可,然后右键点击keil工程中Target1,选择OptionsforTarget‘Target1’中Output,选择CreatHEXfile,设定好了后,点击编译,成功编译后,便得到test.hex文件,再打开proteus仿真模型,双击AT89C51芯片,加载test.hex文件,运行便得到了任务要求的效果。
七、调试运行及分析
修改完,经过编译正确,将编译好的hex文件导入proteus软件中进行仿真,
见图4。
当水位低于下限
,B、C
未触发时
,抽水电机运行抽水
,指示灯点亮。
当水位高于下限低于上限,B触发,C
当水位上升至上限
均触发时
,抽水电机停止抽水
,指示灯灭。
出现错误时,电机停止运转,指示灯闪烁。
图10proteus仿真模型
八、心得体会
(1)在第一次设计与仿真练习过程中遇到了许多的问题其中:
在改写嵌入C语言编译时因为没有屏蔽原程序中的void)(argc);
语句导致程序无法编译。
(2)在第一次的仿真控制8个LED灯时,8个LED灯全都点亮。
开始时以为是程序模型的错误,经过多次的检查证实了程序模型没有错误。
最后在同学的帮助下,发现了是在嵌入C语言编译中,rt_OneStep();
没有放入主函数中。
(3)在水塔水位机电系统设计与仿真实验中:
仿真时发现了proteus仿真模型的运行状态不正确,通过多次的检查发现了在stateflow建模时有一个输入端口没有大写,导致输入端口的信号不能与模型连接。
(4)通过本次水位控制系统的Matlab机电控制系统设计与仿真,
使我Matlab的应用有了一个深刻的认识,也有了一个全面的提高。
这主要得益老师耐心的教诲与同学们提供资料与帮助的结果。
通过这次课程设计,我学到了一个全新的软件,让自己在理论知识和软件操作能力方面都得到了很好的训练!
还学会了充分利用网络资源等一切可以利用的资源
九、参考文献
[1]王静霞.单片机应用技术,电子工业出版社.2009.
[2]Mathworks
Corp.
Stateflow
User'
s
Guide
R2013a[Z].2013.
[3]刘杰.基于模型的设计—MCU篇,北京航空航天大学出版社.2011.
[4]张威.
Matlab.
Stateflow逻辑系统建模,西安电子科技大学出版社.2007.
十、致谢
在本次课程设计中许多同学给予我帮助,解决了不少在课程设计中遇到的问题。
同时也帮助我自己获取了许多过去没有的学到的知识。
在这里我要特别感谢唐伟杰老师的耐心教导,郑建伟同学的建议和提醒!
!
/*
*File:
ert_main.c
*
*CodegeneratedforSimulinkmodel'
untitled'
.
*Modelversion:
1.6
*SimulinkCoderversion:
8.5(R2013b)08-Aug-2013
*C/C++sourcecodegeneratedon:
SunOct2623:
45:
212014
*Targetselection:
ert.tlc
*Embeddedhardwareselection:
Intel->
8051Compatible
*Codegenerationobjectives:
Unspecified
*Validationresult:
Notrun
*/
#include<
stdio.h>
/*Thisert_main.cexampleusesprintf/fflush*/
#include"
untitled.h"
/*Model'
sheaderfile*/
rtwtypes.h"
sbitP1_0=P1^0;
sbitP1_1=P1^1;
sbitP1_2=P1^2;
sbitP1_3=P1^3;
/**Associatingrt_OneStepwithareal-timeclockorinterruptserviceroutine
*iswhatmakesthegeneratedcode"
real-time"
.Thefunctionrt_OneStepis
*alwaysassociatedwiththebaserateofthemodel.Subratesaremanaged
*bythebaseratefrominsidethegeneratedcode.Enabling/disabling
*interruptsandfloatingpointcontextswitchesaretargetspecific.This
*examplecodeindicateswheretheseshouldtakeplacerelativetoexecuting
*thegeneratedcodestepfunction.Overrunbehaviorshouldbetailoredto
*yourapplicationneeds.Thisexamplesimplysetsanerrorstatusinthe
*real-timemodelandreturnsfromrt_OneStep.*/
voidrt_OneStep(void)
{staticboolean_TOverrunFlag=0;
/*Disableinterruptshere*/
/*Checkforoverrun*/
if(OverrunFlag){
rtmSetErrorStatus(untitled_M,"
Overrun"
);
return;
}
OverrunFlag=TRUE;
/*SaveFPUcontexthere(ifnecessary)*/
/*Re-enabletimerorinterrupthere*/
/*Setmodelinputshere*/
untitled_U.In2=P1_0;
untitled_U.In1=P1_1;
/*Stepthemodel*/
untitled_step();
/*Getmodeloutputshere*/
P1_2=untitled_Y.Out2;
P1_3=untitled_Y.Out1;
/*Indicatetaskcomplete*/
OverrunFlag=FALSE;
/*RestoreFPUcontexthere(ifnecessary)*/
/*Enableinterruptshere*/}
*Theexample"
main"
functionillustrateswhatisrequiredbyyour
*applicationcodetoinitialize,execute,andterminatethegeneratedcode.
*Attachingrt_OneSteptoareal-timeclockistargetspecific.Thisexample
*illustateshowyoudothisrelativetoinitializingthemodel.*/
int_Tmain()
{/*Unusedarguments*/
//(void)(argc);
//(void)(argv);
/*Initializemodel*/
untitled_initialize();
/*Attachrt_OneSteptoatimerorinterruptserviceroutinewith
*period0.5seconds(themodel'
sbasesampletime)here.
/*Disablert_OneStep()here*/
/*Terminatemodel*/
untitled_terminate();
return0;
*Filetrailerforgeneratedcode.
*[EOF]
附录
rt_zcfcn.c
Notrun*/
rt_zcfcn.h"
/*Detectzerocrossingsevents.*/
ZCEventTypert_ZCFcn(ZCDirectionzcDir,ZCSigState*prevZc,real_TcurrValue)
{
slZcEventTypezcsDir;
slZcEventTypetempEv;
ZCEventTypezcEvent=NO_ZCEVENT;
/*assume*/
/*zcEventmatrix*/
staticconstslZcEventTypeeventMatrix[4][4]={
/*ZERPOSNEGUNK*/
{SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_Z2P,SL_ZCS_EVENT_Z2N,SL_ZCS_EVENT_NUL},/*ZER*/
{SL_ZCS_EVENT_P2Z,SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_P2N,SL_ZCS_EVENT_NUL},/*POS*/
{SL_ZCS_EVENT_N2Z,SL_ZCS_EVENT_N2P,SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_NUL},/*NEG*/
{SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_NUL,SL_ZCS_EVENT_NUL}/*UNK*/};
The
*callsyntaxforrt_OneStepis
*rt_OneStep();
//fflush((NULL));
while(rtmGetErrorStatus(untitled_M)==(NULL)){
/*Performotherapplicationtaskshere*/
rt_OneStep();
}
else{
currEv=SL_ZCS_EVENT_NUL;
/*UpdateprevZc*/
tempEv=(slZcEventType)(currEv<
<
2);
/*shiftleftby2bits*/
*prevZc=(ZCSigState)((currSign)|(tempEv));
if(currEv&
SL_ZCS_EVENT_ALL_DN){
zcEvent=FALLING_ZCEVENT;
}elseif(currEv&
SL_ZCS_EVENT_ALL_UP){
zcEvent=RISING_ZCEVENT;
}else{
zcEvent=NO_ZCEVENT;
returnzcEvent;
}/*rt_ZCFcn*/
/*getprevZcEventandprevZcSignfromprevZc*/
slZcEventTypeprevEv=(slZcEventType)(((uint8_T)(*prevZc))>
>
slZcSignalSignTypeprevSign=(slZcSignalSignType)(((uint8_T)