在学习LabView面向对象编程过程中,相信大家也都接触到了Actor Framework。该框架于2010年NI Week首次公布,经过多年不断迭代更新,逐渐成为LabVIEW中最为重要的并发开发框架。
我们将通过本期内容综合学习Actor Framework的一些基础知识,包括Actor的创建、方法的重写、辅助循环的构建、Actor嵌套关系、以及接口消息的应用。让大家对AF能有一个更深入的了解。
本文教程: Actor Framework练习—仿真线性编码器
一、整体功能展示:
程序主体由三部分构成,分别为Business Logic、Linear Encoder、User Interface。
用户操作Linear Encoder产生数据,分两种形式更新到User Interface:单点实时更新、多点缓冲更新(利用队列缓冲区溢出产生注册事件)。最终实现的效果如下图所示:
接下来小编将带着大家从零开始,完成这个程序的编写。
二、设计实现:
1.建立Actor并构造辅助循环
首先我们创建一个空白项目Simulate Linear Encoder(项目需要先保存),在我的电脑右键—>新建 —>操作者。
分别创建Business Logic、Linear Encoder、User Interface三个Actor。
接下来我们来重写Actor的方法,可以重写Actor Core构建辅助循环以实现用户交互界面。我们可以选中Linear Encoder这个类,右键—>新建—>用于重写的VI。
可以看到Actor类支持重写的方法,构建辅助循环我们一般需要重写:Actor Core、Pre Launch Init、Stop Core这三个VI。
如果想要在Linear Encoder的Actor Core构建用户交互界面,就需要一个额外的辅助循环以响应前面板的事件。格外要注意的是辅助循环的停止,不然可能会无法正常退出程序。
正常程序关闭时,需要向Actor Core 发送Stop Message消息,以关闭Actor Core执行消息的循环。
我们可以利用注册消息的形式,在Pre Launch Init中创建用户事件,当执行Stop Core时产生注册事件,辅助循环响应停止。现在我们来重写Pre Launch Init,右键—>用户界面—>事件,就可以看到关于用户事件相关API。
我们要在Pre Launch Init中创建用户事件并将事件的输出存到LinearEncoder的私有数据中,双击这个带红色钥匙标识项,便可以看到类存放私有数据的地方。
创建一个Events的簇用于存放注册事件,将其拖进类私有数据簇进行保存。
其中Stop用户事件的引用句柄可以通过右键“用户事件输出”创建输入控件得到。
这样我们便可以在Pre Launch Init中将产生用户事件的引用句柄存到类私有数据中(注意用户事件数据类型需要命名)。
接着我们重写Stop Core,产生用户事件并销毁用户事件。
接下来便可以重写Actor core 来搭建辅助循环。
辅助循环完成之后,便可以开始前面板用户交互界面的搭建。
2.重构Actorcore前面板
这是Actor core前面板,我们一般情况下不需要在程序运行时显示这些,可以隐藏这些控件或者在VI前面板中寻找一个空白的地方,放置一个水平指针滑动杆以模拟线性编码器的位置输出,如下图所示:
将Linear Encoder的Actor Core的VI窗口外观属性更改为自定义,调用时显示前面板(User Interface的Actor Core也需要进行设置)
3.构造传输数据的方法
本次范例中模拟位置数据更新到用户界面方式有两种形式:单点实时更新,多点缓冲更新(利用队列缓冲区溢出产生注册事件)。
接下来我们处理多点的缓冲数据:在Actor core中增加数值控制值改变的事件。
我们新增一个方法Add Value to Buffer.vi用于将数据存储到队列的缓冲区,右键LinearEncoder类,新建基于静态分配模板的VI(动态分配模板的VI,子类继承可以重写)。
我们先在类私有数据的簇中,增加队列引用句柄。
回到Pre Launch Init中,在初始化时创建用于存放缓冲数据的队列,将队列引用存放在私有数据中。队列缓冲大小设置为100,即超出100个数据,在入队列时会造成超时。
同样的在Actor停止时,需要将队列的句柄释放,即在Stop core增加释放队列引用。
队列的准备工作完成,我们回到新增的Add Value to Buffer.vi处理缓冲数据,可以通过入队列是否超时来判断缓冲区是否满100个点的数据,满足则将数据更新出去。
(此时Business Logic的接口消息还未创建,数据并未传递出去)
接下来我们重写User Interface的Actor core,按上面同样的步骤构建辅助循环。同时增加两个用户事件,分别用于更新单点位置数据和波形数据。
User Interface —— Pre Launch Init 程序框图:
User Interface —— Stop core 程序框图:
User Interface —— Actor core 程序框图:
接着我们构建User Interface Actor core的前面板,需要波形图用于显示100个点的缓冲数据、数值控件显示Current Position如下图所示:
在事件结构中创建两个用户事件的响应:
接着我们去创建两个静态分配的VI,分别是:Update Current Position.vi和Update Graph.vi。这两个VI用于产生用户事件,由Business Logic 发送消息将Linear Encoder 产生的数据更新到前面板。
记得在前面板连接好输入输出接线端,分别在Update Current Position.vi和UpdateGraph.vi上右键—>操作者框架—>创建消息,LabIVEW会自动用脚本帮我们创建好操作者消息,User Interface的内容就完成了。
4.接口的应用
现在我们来处理Business Logic的部分,用户逻辑是将Linear Encoder传递进来的数据更新到User Interface,我们不能直接在Linear Encoder中发送Business Logic的更新数据消息,这样会使Linear Encoder与Business Logic产生耦合,所以我们使用接口来解耦,进行数据的传递。
右键我的电脑—>新建—>接口,命名为BusinessLogic Interface。
右键接口—>新建—>基于动态模板分配的VI。
分别在前面板放置数值控件、数值数组控件作为输入端,并连接好接线端。
Position Updated.vi
Encoder Buffer Updated.vi
分别右键两个方法—>操作者框架—>创建消息,为其创建消息,如下所示:
接口创建完毕,我们右键Business Logic类,选择属性为它继承这个接口。
继承接口后我们会发现Business Logic这个Actor断线了,这是因为继承接口后必须重写接口方法。右键Business Logic新建—>用于重写的VI。
可以看到增加了两个带星号的方法,也就是我们刚才接口里创建的两个方法。我们按住Ctrl同时选中Actor Core.vi、Encoder Buffer Updated.vi、Position Updated.vi对这三个VI进行重写。
首先对Actor core进行重写,我们需要在这个Actor内启动Linear Encoder、User Interface,并将两个Actor的消息队列引用,保存到Business Logic的私有数据中,以便在该Actor内可以随时引用。
此处用的是启动嵌套操作者函数,它会将Calling Actor与 Nested Actor操作者关联起来,Launch Nested Actor有一个Auto-Stop默认为T,为T状态下启动 NestedActor会将队列进行保存,当此Calling Actor退出时便会自动关闭其下所有的Nested Actoor。
接着我们重写Encoder Buffer Updated.vi。
此处的两个Send Message:
回到Linear Encoder Actor补全Business Logic传递数据的部分,打开Add Value to Buffer.vi ,用接口消息Send EncoderBuffer Updated.vi将数据传递出去。
最后打开Linear Encoder的Actor core,将Linear Encoder Position值传递到Add Value to Buffer.vi以及接口消息PositionUpdated.vi中。
5.创建启动器
这样我们的程序就编写完毕了,可以创建一个Launcher.vi用于启动Business Logic,验证最终成果。
三、内容总结:
1、创建Actor,重写Actor Method;
2、构建辅助循环,利用注册事件关闭辅助循环;
3、学习使用接口,进行模块间解耦;
4、了解嵌套操作者之间的启停机制。
注意:本文中的示例程序将会放在以下百度网盘链接中,大家可自行下载并参考学习,注意软件版本哦(本篇练习使用的LabVIEW版本为2020)~
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !