LabVIEW设计模式汇总

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

LabVIEW设计模式汇总
本文归纳了LabVIEW中常用的几种设计模式,介绍了各种设计模式的特点及适用范围,并提供了每种设计模式对应的典型应用实例。

1 标准状态机
1.1简介
状态机(State Machine)是编程中经典的设计模式之一。

状态机对系统所有可能的状态进行罗列,在每个状态分支中执行该状态的代码,并指明系统要执行的下一个状态。

状态机能清晰和准确地完成与状态密切相关的任务。

1.2结构
图1-1为典型的标准状态机结构。

系统包含“Initialize”,“Idle”,“Case1”,“Case2”,“Stop”五个状态;系统可以在“Initialize”中初始化系统参数,在“Idle”中专门做状态选择处理,“Case1”和“Case2”为用户自定义的状态分支,“Stop”状态使系统停止运行。

图1-1 标准状态机结构
1.3要点
(1)状态枚举常量
该枚举常量包含了系统所有可能的状态,每次可以选择一个指定的状态。

(2)带移位寄存器的while循环
状态机通过while循环上的移位寄存器传递下一个要执行的状态,每次循环只能执行一个条件分支。

(3)条件结构
该条件结构的每个分支对应一个系统的可能的运行状态。

Tips:
●可以将枚举常量设计为自定义控件类型。

当系统状态需要修改时,只需要修改一次“自定义控件”即
可更新整个程序中所有的枚举常量。

●将枚举常量连接到条件结构的选择器接线端后,右击条件结构边框,选择“为每个值添加分支”,可
以轻松地为条件结构实现分支配置。

1.4实例
(1)情景:
使用温度监控系统监测当前温度,当温度超过高温阈值时发出“高温警报”,当温度低于冷冻阈值时发出“冷冻警报”。

(2)代码:
详见附件中的“标准状态机”项目文件。

图1-2 前面板设计
图1-3 程序框图设计
1.5小结
标准状态的应用非常广泛,它的特点是:
(1)系统的所有状态和转换条件都是可以提前预期设定的,而不是随机产生的;
(2)系统一次只能执行一个状态,不适合做并行任务处理。

如何定义状态是其中最关键的因素。

状态机的状态要设计全面,指向明确合理。

在着手编程之前,需要先确定系统的状态转移图,检查是否有状态遗漏,各状态执行代码是否均衡合理,是否方便以后的需求拓展。

虽然标准状态机具有结构简单,设计方便的优点,但由于它要求系统的状态必须是预知的,且当前状态只能由上一个状态决定。

当系统需要人机交互或者其他复杂操作时,标准状态机则无能为力,还需要采用其他的设计结构。

1.6参考资料与范例
[1] https:///content/docs/DOC-14959
[2] https:///content/docs/DOC-22972
[3] https:///content/docs/DOC-4594
[4]LabVIEW 2012\examples\apps\testseq.llb\State Machine Test equencer.vi
2队列消息处理器
2.1简介
队列消息处理器与标准状态机并没有太大区别,不同点在于队列消息处理器是使用数组(或队列)来储存状态,而标准状态机使用的是自定义枚举控件传递状态。

正因为如此,导致队列消息处理器有以下优势:
(1)通过数组(或队列)添加状态,可以一次性指定多个即将执行的状态;
(2)状态的数据类型更灵活,可以是数据、布尔、字符串等;
(3)使用队列添加状态时,可以在队列消息处理器循环外部向队列中插入状态,改变状态的执行顺序。

2.2结构
在LabVIEW中通常使用数组或队列实现队列消息处理器,如图2-1所示。

前者使用“创建数组”和“删除数组元素”函数,后者使用“元素入队列”和“元素出队列”函数。

图2-1 典型的队列消息处理器
2.3要点
(1)使用数组操作函数的队列消息处理器
“创建数组”函数可以向消息数组中一次添加多个消息,“删除数组元素”函数的“已删除的部分”接线端与条件结构的选择器接线端相连。

(2)使用队列操作函数的队列消息处理器
“元素入队列”函数可以一次向队列中添加多个消息,如果要新加入的消息立即执行,请使用“队列最前端插入元素”函数添加该消息,而不是普通的“元素出队列”函数。

“元素出队列”函数读出队列中最前端的消息并同时将其从队列中删除。

2.4实例
(1)情景:
使用温度监控系统监测当前温度,当温度超过高温阈值时发出“高温警报”,当温度低于低温阈值时发出“冷冻警报”,并同时记录该温度值。

(2)代码:
详见附件中的“队列消息处理器”项目文件。

图2-2 前面板设计
图2-3程序框图设计
2.5小结
队列消息处理器与标准状态机非常相似,队列消息处理器同标准状态机一样,需要注意分支的合理划分。

它的特点是:
(1)传递的消息是动态变化的,可以一次添加多个消息;
(2)消息的数据类型更加灵活,可以是数值、布尔、字符串等;
(3)使用队列传递状态消息时,可以在循环外部向队列中插入消息,方便对队列消息处理器的控制。

2.6 参考资料和范例
[1] /white-paper/14119/en
[2]/93-2227024418212703582135328357743574527169243352004320108mdashm dash38431210152804024687227882970222120.html
[3]LabVIEW 2012\examples\general\queue.llb\Queue Message Logging.vi
[4]LabVIEW 2012\examples\general\uievents.llb\Queued Message Handler.vi
3事件结构
3.1简介
事件结构是LabVIEW中另一种非常重要的设计结构。

在事件结构发明之前,系统需要不断地“轮询”用户事件是否发生,执行效率非常低。

事件结构类似于“中断”功能,只有当事件发生后,CPU才对其进行处理,事件没发生之前,CPU可以执行其他进程或任务。

事件结构能大大节约系统资源,同时也避免了事件遗漏。

3.2结构
事件结构包含五个基本元素。

(1) 事件选择器——指定本分支所处理的用户事件;
(2) 事件数据节点——用于识别事件发生时LabVIEW返回的数据;
(3) 事件过滤节点——只有在过滤型事件分支中才会显示。

过滤事件能在LabVIEW处理事件之前告知用户该事件已发生,使用户可以自定义处理该事件。

(4) 超时接线端——当在规定时间范围内没有任何指定的事件发生,则进入超时分支;
(5) 动态事件接线端——需要与“注册事件”函数配合使用,可以在程序运行时处理由程序内部指定希望产生的事件。

图3-1 事件结构
3.3要点
(1)事件结构
用来监测所有的用户交互操作。

(2)while循环
为了多次处理事件,事件结构一般要放在while循环中,且一个程序只需要有一个事件结构。

Tips:
●事件分支中的处理程序越快越好。

如果在下一个用户交互事件发生时,上一个事件还没有处理完,则
不能及时响应下一个事件。

●通常,LabVIEW只有在用户直接与活动前面板交互时才产生用户界面事件。

使用共享变量、全局变量、
局部变量、DataSocket时,LabVIEW不生成事件。

但使用值(信号)属性可以产生“值改变”事件。

3.4案例
(1)情景:
使用温度监控系统监测当前温度。

当点击“开始采集”按钮时,系统采集一次当前温度
值;当点击“数据分析”按钮时,系统对最近一次的温度值进行分析,根据温度所处范围发出高温报警或冷冻报警;当点击“停止”按钮时,系统停止。

(2)代码:
详见附件中的“事件结构”项目文件。

图3-2 前面板设计
图3-3程序框图设计
3.5小结
事件结构是LabVIEW中的经典设计结构,适合用户交互事件较多的应用。

但事件结构需要注意的细节也特别多,处理不好很容易发生锁死或错误。

事件结构单独使用时只能执行一些简单的独立事件,我们往往将它应用在其他设计模式中发挥更大的作用。

3.6参考资料与范例
[1]/reference/zhs-XX/help/371361H-0118/lvconcepts/notify_and_filter_events/
[2]/reference/zhs-XX/help/371361J-0118/lvconcepts/using_events_in_labview/
[3]/reference/zhs-XX/help/371361H-0118/lvhowto/hndlstoploopbool/
[4]/reference/zhs-XX/help/371361H-0118/lvhowto/dynamic_register_event/
[5]LabVIEW 2012\examples\general\templates\Top Level
App\Acquire-Analyze-Present.llb\Acquire-Analyze-Present.vi
4事件状态机
4.1简介
事件状态机是将事件结构与状态机结合的设计模式,常用来处理多个用户界面事件。

在LabVIEW启动界面中通过“创建项目”-“简单状态机”得到的设计模板,即为本节所介绍的事件状态机。

4.2结构
图4-1为典型的事件状态机结构,包含“Initialize”,“Wait for Event”,“User State 1”,“User State 2”,“Stop”五个状态;其中,系统初始化后会长时间停留在用于监测用户界面事件的“Wait for Event”分支。

当对应的用户事件产生时,系统转向执行对应的处理分支,执行完毕后返回“Wait for Event”分支。

图4-1 事件状态机的基本结构
4.3 要点
(1)事件结构分支
事件结构是事件状态机的核心,完成对所有用户交互事件的实时监测。

(2)其他分支
其他分支的执行速率要尽可能快,否则会影响系统对用户交互事件的响应速率。

4.4实例
(1)情景:
使用温度监控系统监测当前温度。

当点击“开始采集”按钮时,系统以10Hz的采样率连续采集50个温度值;当点击“数据统计”按钮时,系统对最近一次的采集数据进行统计,计算出最高温度,最低温度和平均温度;当点击“数据存储”按钮时,系统将最近一次的采集数据进行保存,文件名称为用户点击“数据存储”按钮的时间;当点击“数据回放”时,系统打开文件对话框,用户选择自己感兴趣的记录文件进行回放;当点击“停止”按钮时,系统停止。

(2)代码:
详见附件中的“事件状态机”项目文件。

图4-2 前面板设计
图4-3程序框图设计
4.5小结
与标准状态机不同,事件状态机的特点是:
(1)主要用于需要响应多种用户事件的系统;
(2)系统长时间处于一个包含事件结构的状态分支中;
(3)状态机一次只能处理一个分支,不适合做并行的事件处理。

事件状态机适用于简单的事件处理。

但事件结构与其他条件分支共享一个循环,当系统在某个条件分支中执行时间较长时,会导致下一次事件响应延迟。

另外,对于一个事件发生,对应处理该事件的条件分支只能运行一次。

如果我们希望用户按下“开始采集”按钮后,程序连续不断地运行“采集”条件分支,则事件状态机无法满足该需求,我们需要使用其他设计模式来实现。

4.6参考资料与范例
[1] https:///content/docs/DOC-11192
[2] /reference/zhs-XX/help/371361H-0118/lvhowto/hndlstoploopbool/
[3] LabVIEW 2012\examples\general\uievents (Full).llb\New Event Handler.vi
5主从设计模式
5.1简介
主从设计模式由一个主循环(Master)和一个或多个从循环(Slave)组成。

该设计模式将任务分配到多个循环中并行处理,提高了系统效率,体现了LabVIEW支持多线程的优点。

利用通知器一对多的信息传递特点,主从设计模式常常用来同步控制几个速率不同的并行循环任务;利用通知器潜在有损的传输特性,可以用来低速执行数据显示,但不适合于数据记录。

Tip:通知器类似于通信中的广播方式,一点发出消息,其他所有接收点都可以同时接收到,因此特别适用于一对多的信息传播。

通知器操作函数不缓冲已发送的消息,如果消息被发送后没有任何节点在等待,则当另一消息被发送后数据将丢失,通知器的执行类似于单元素,有损耗的绑定队列。

5.2结构
图5-1为主从设计模式的基本结构,程序上方的while循环为主循环(Master),下方的循环为从循环(Slave)。

主循环通过通知器操作函数控制从循环运行。

图5-1 主从设计模式的基本结构
5.3要点
(1)一个主循环,多个从循环
多个从循环同时接收主循环的命令控制,但它们的执行速率可以不同。

(2)通知器
只能在主循环内使用“发送通知”函数,从循环内使用“等待通知”函数。

Tip:注意各通知器(或队列)释放引用的时机。

如果从循环中的“等待通知”函数还在执行,而其他程序部分已经释放了该通知器的引用,则会发生错误。

5.4实例
(1)情景:
系统同时监控环境的温度和湿度。

当点击“开始采集”按钮时,系统开始同时采集用户指定个数的温度值湿度值,“开始按钮”的文字说明变为“正在采集”,当采集结束后恢复为“开始采集”。

当点击“退出”按钮时,系统停止运行。

(2)代码:
详见附件中的“主从设计模式”项目文件。

图5-2 前面板设计
图5-3 程序框图设计
5.5小结
由于通知器的“一对多”特性,主从设计模式经常被用来控制几个不同速率的循环。

但由于通知器使用潜在有损的传输机制,如果主从循环的执行速率不同,常常会发生数据丢失现象。

如果需要高速和大量的数据传递,这种设计模式就不太合适,推荐使用生产者和消费者模式。

5.6参考资料与范例
[1] https:///content/docs/DOC-29591
[2] https:///content/docs/DOC-14758
[3]LabVIEW 2012\examples\general\notifier.llb\Pass Data with Notifiers.vi
6生产者/消费者(数据)
6.1简介
在生产者/消费者(数据)结构中,生产者不断“生产”数据,通过队列传递给消费者进行“消费”。

该结构的一个突出特点就是队列充当了生产者和消费者循环之间的“缓存”作用,生产者循环和消费者循环速率可以不同。

当生产过剩,缓存区内的数据会越来越多;当消费过快,缓存区数据会越来越少,当缓存为空时,消费者变为等待状态,直至缓冲区中出现可用数据。

在生产者/消费者(数据)结构中,最常见的问题就是内存溢出,此时需要提高消费者循环的执行速率或降低生产者循环的速率。

6.2结构
图6-1为生产者/消费者(数据)的基本结构。

程序上方的while循环是生产者循环,生成所需要的数据。

程序下方的while循环是消费者循环,完成数据处理。

两者通过队列操作函数完成数据传递。

图6-1 生产者/消费者(数据)基本结构
6.3要点:
(1)while循环:并行循环充当“生产者”和“消费者”的角色。

事实上,生产者/消费者(数据)模型中,不拘泥于只使用两个循环,根据实际需要,可以使用多个“生产者”,也可以使用多个“消费者”。

但由于消费者从队列中取出元素后会将原数据从队列中删除,因此多个消费者共存时,消费者消费的将会是不同的数据。

因此,在多个“生产者”或者“消费者”并存时,它们之间的数据传递也会变得复杂,编程时需要留意。

(2)队列函数:在并行循环结构之间传递数据。

编程者可以灵活使用各个队列操作函数。

例如使用“队列最前端插入元素”可以使消费者接收到最新的数据。

6.4实例
(1)情景:
使用温度监控系统监测当前温度,系统采样率为100Hz。

当温度超过高温阈值时发出“高温警报”,当温度低于冷冻阈值时发出“冷冻警报”。

(2)代码:
详见附件中的“生产者/消费者(数据)”项目文件。

图6-2 前面板设计
图6-3 程序框图设计
6.5小结
在工业应用中,往往需要同时采集和处理大量数据,因此生产者/消费者(数据)设计模式的应用非常广泛。

它的特点是:
(1)多线程同步执行,程序执行效率高;
(2)适合大量的数据流处理。

生产者/消费者(数据)结构并没有涉及人机交互过程,如果需要进行大量的人机交互,可以采用生产者/消费者(事件)结构。

6.6 参考资料与范例
[1] https:///content/docs/DOC-14758
[2] https:///content/docs/DOC-8962
7生产者/消费者(事件)
7.1简介
生产者/消费者(事件)设计模式与生产者/消费者(数据)设计模式非常类似,区别是两者处理的对象不同,前者为数据,后者是事件。

在生产者/消费者(事件)结构的生产者循环中,事件结构保持监测前面板产生的用户交互事件,并将事件信息送入队列;在消费者循环中,根据队列中的事件信息执行对应的处理操作。

相比事件状态机,生产者/消费者(事件)体现了LabVIEW支持多线程的特点,提高了系统的执行效率。

7.2结构
图7-1为生产者/消费者(事件)的基本结构,由while循环,事件结构和传递事件信息的队列组成。

图7-1 生产者/消费者(事件)基本结构
7.3要点
(1)事件结构
专门用来监测所有的用户交互操作。

(2)while循环
遵循程序中最好只有一个事件结构的原则,生产者/消费者(事件)结构一般只使用一个生产者,但可以有多个消费者(需要用到多个队列)。

Tip:推荐使用的循环同步停止方式
当生产者循环监测到用户按下“Stop”按钮时,将“停止”消息写入队列,消费者循环接收到该消息后转向“停止”分支,在该分支中,程序将“True”传递给循环条件接线端。

7.4实例
(1)情景:
温度监控系统监测当前温度。

当点击“开始采集”按钮时,系统开始连续采集50个温度值,采样率为10Hz;当点击“数据统计”按钮时,系统对最近一次的采集数据进行统计,
计算出最高温度,最低温度和平均温度;当点击“数据保存”按钮时,系统将最近一次的采集数据进行保存;当点击“数据回放”时,系统打开文件对话框,用户选择自己感兴趣的记录文件进行回放;当点击“停止”按钮时,系统停止。

(2)代码:
详见附件中的“生产者/消费者(事件)”项目文件。

图7-2 前面板设计
图7-3 程序框图设计
7.5小结
生产者/消费者循环(事件)结构适合需要处理多个用户事件的系统。

但该结构也存在缺点,例如生产者发出一次指令,消费者循环只能运行一次。

但在实际的数据采集应用中,我们更希望生产者发出“开始”指令后,消费者循环能开始连续采集,而不是只采集一段数据。

因此,单一的生产者/消费者(事件)结构也有一定的局限性。

7.6参考资料与范例
[1] https:///content/docs/DOC-30005
[2] https:///content/docs/DOC-2145
[3] https:///content/docs/DOC-14974
8 混合设计模式
8.1简介
在实际工程应用中,用户的需求往往是多元化的,既需要数据连续采集和处理,同时还希望系统能及时响应自己的特殊操作。

但标准设计模式能实现的功能往往比较单一,要么只能处理分立的几个事件,要么只能执行不涉及任何用户交互操作的连续数据任务。

可见,在复杂的系统任务中,单一的设计模式已经不能满足需求,我们往往会用到组合了多个标准设计模式的混合设计模式。

混合设计模式能结合各个设计模式的优点,满足更多的任务需求。

但不可避免地,功能越强大,系统结构也越复杂。

本节给出了一种典型的混合设计模式,实现了温度测量系统的数据采集、存储和分析功能。

在LabVIEW自带的项目范例“连续采集与记录”也是一种典型的混合设计模式,但程序结构较复杂,供感兴趣的读者参考。

8.2结构
本节介绍的一种混合设计模式如图8-1所示。

该结构是由一个生产者/消费者(事件)与两个消息队列处理器组合而成:
图8.1 一种典型的混合设计模式结构
8.3要点
(1)指令中心
程序上方的两个循环组成系统的指令中心,采用生产者/消费者(事件)模式设计,实现监测用户事件和分配任务命令的功能。

(2)功能模块
程序下方的两个循环是系统的功能模块,采用消息队列处理器模式设计,完成系统的两个独立功能。

功能模块可以在自身内部产生消息,也可以接收指令中心的消息。

功能模块的设计结构可以多种多样。

如果要连续执行,可以采用队列消息处理器,如果只需要分步骤执行一次,使用标准状态机就可以。

(3)队列(或通知器)
指令中心和功能模块,以及功能模块之间往往有很多数据交流。

队列和通知器是两种主要的数据传递方式,两者的区别是:队列适合“多对一”的传递方式,通知器适合“一对多”的传递方式,但通知器属于潜在有损的传输机制,不适合用于高速大量的数据处理过程。

8.4案例
(1)情景:
设计温度监控系统,能同时控制连续的温度采集、存储和报警功能,允许用户自由设置系统参数和查看历史记录文件。

(2)代码:
详见附件中的“混合设计模式”项目文件。

图8-2 前面板设计
图8-3 程序框图设计
Tips:
●队列消息处理器中需要注意的问题
(1)指令中心发出的“停止”命令建议使用“队列最前端插入元素”函数,而不是普通的“元素入队列”函数,以便立即停止功能模块;
(2)在功能模块的“停止”分支中要执行清除消息队列操作,消除队列中残留的消息(“开始”)影响,否则循环不会停止。

(3)注意释放队列(或通知器)引用的时机。

避免释放队列(或通知)引用之后,还有“元素出队列”和“等待通知”VI在运行。

一般将所有释放引用放在程序最末端执行。

●子VI与主VI的数据传递
在子VI的循环内的显示控件不能实时将数据传递到主VI。

解决的办法有两种:使用“控件引用”函数;使用队列。

8.5小结
在实际工程应用中,大多数应用的功能需求都会比较复杂,往往需要结合各种基本设计模式的特点,通过混合设计模式来实现。

结束语
没有一种万能的设计模式能恰好满足世界上所有的应用需求。

因此,编程最重要的不是编程者的技巧,而是编程者的思路。

唯有深入领会各种标准设计模式的设计思想,才能将它们灵活地运用在各式各样的应用中。

附件:
LabVIEW设计模式汇总-2012.zip。

相关文档
最新文档