LabVIEW中测试测量数据的存储

LabVIEW中测试测量数据的存储
LabVIEW中测试测量数据的存储

这里说的测试测量数据是指配合NI的硬件,如PXI卡采集所得的测试测量数据。对其他的测试测量应用场景我还不熟悉。

NI原先是缺乏一个比较优秀的测试测量数据存储方案的,NI后来也意识到了这个问题,于是在德国收购了一家公司,这家公司专做数据存储(也包括显示、报表等),于是NI在数据的采集、存储、显示这方面的产品线已经比较齐全了。

NI现在主推的一个数据存储逻辑模型叫做TDM(Technical Data Management),具体的方案可见:

NI TDM Data Model

这个模型的特点可以简单概括为:清晰的层次结构以及支持各层次的描述性信息。具体来讲,一个TDM模型的数据文件可以分为三层,分别为文件(File)、组(Group)和通道(Channel),在每个层次上,都有NI定义好的一些属性,同时,用户也可以自定义属性。

这样的一种数据模型很容易被理解和接受。比较符合实际的应用需求。比如用NI的采集卡采集电压数据。一块卡上一共8个通道。每个通道每次采集的数据都可以保存为一个“通道(channel)”,8个通道一次采集的数据可以组成一个组(group),每天采集一次,n天就形成n个组,每个组都有8个通道,所有的数据都写在同一个文件(file)里。其他卡采集的数据放在不同的文件中。

除了直接采集到的数据(可称之为Raw Data)之外,总要写点其他信息的,比如采集卡到底是什么型号,每次采集都是谁来完成,采集的是电压还是电流,单位是伏特还是千伏等等。这些信息就称为描述性信息(Meat Data)。这些信息写在别的文件里面总不太容易管理,最好写在一个文件中。因此TDM模型也支持将这些描述性信息写在同一个文件中。

注意一下,我在这里说的是TDM的“逻辑”模型,并不是指他的物理存储结构。在NI,有数种文件格式都支持TDM的模型,但是他们的物理存储方式大相径庭,这个以后再写。

这种TDM模型的测试测量数据文件,是NI软件平台中通用的文件,除了LabVIEW外,很多其他的NI软件产品都支持这种模型,比如DIAdem、CVI、Singal Express等等。

在LabVIEW中,分别有三套API支持TDM模型的数据文件,他们分别是:

Measurement File/Storage VIs/TDMS

(图片采自LabVIEW 8.5.1 Professional)

这三套API分别对应着三种应用的难易级别,由易而难。具体以后再介绍。

下次写一下我对TDM数据模型的看法(优缺点),以及简单介绍相关的文件格式。

在分析TDM模型的优劣势之前,我想最好先罗列一下一些数据文件格式的技术要求。

NI软件平台上针对于测试测量的数据,有很多不同的文件格式,其中有几种是支持TDM模型的。并不是说这些文件都能满足以下技术要求,我只是先罗列出来:

1)写文件速度必须要快。很多情况下需要一边采集数据一边就把数据写到

文件中,采集卡的速度已经相当快了,这时候瓶颈常常是在写文件这个步骤上。相反,读文件可能并没有如此高的要求。

2)向文件追加(append)数据的时候,速度要快,这个时候不能读取文件中的信息。这其实也是常用的一个use case,采集数据写入文件的动作可能经常要进行(比如在一个循环中),往往又是往同样的文件中写入信息。

3)写文件的速度不能与文件大小成正比。我们希望不管文件有多大,写文件的速度总是保持相对恒定,不能文件越大就写得越慢。

4)支持随机的读取。比如我想读文件中某个位置的某些内容,不能要求把这个位置之前的所有数据都先读出来(即读到内存中)。

5)支持分别读写描述性信息和原始数据。这是上一条的延伸,读描述性信息(meta data)的时候不要求把原始数据(raw data)读进来,同样,读原始数据的时候也不要求把描述性信息读进来,否则,势必影响读文件的速度。

6)对读文件的速度也有一定的要求。这个要求主要来自于搜索数据。无数浩瀚的数据,怎样才能快速的找到用户需要的数据,这一直是一个难题。

7)文件不能太大。存储同样的数据量,文件自然越小越好。

技术要求暂时就写这么多,其实总结起来,无非两点:1)快;2)方便。我们对照TDM的数据模型,对于“快速”,暂时看得不明显(以后可以谈谈为什么TDMS文件可以达到“快速的要求”),但是说它“方便”,还是可以理解的。

这个模型的设计完全是依照用户的应用实例。首先,它是分层次的。比如说我们需要测试汽车发动机的各个指标。我们用8个通道的采集卡采集发动机振动的数据,8个通道分别采集8个部位的振动,存到文件中,作为一个组

(group),组的名字就叫做“发动机振动”。我们还需要采集发动机的进气管、排气管压力,又作为一个组。还要采集发动机的温度,可能也用8个通道的采集卡采集8个部位的温度,每个部位的温度数据作为一个通道(channel)存到文件中,8个通道作为一个组,叫做“发动机温度”等等。我们可能会采集多次,其他参数都不变,只是数据每次都附加在文件的后面。我们有很多的测试工程师,每个工程师做的测试分别存成一个TDM模型的数据文件。可以发现,这样的三层结构还是很清晰的。这就好比用LabVIEW些程序,VI大了,就不知道怎么管理了,那就多用几层SubVI嘛。

其次,它具有描述性信息。比如可能需要把测试的日期、测试者的名字、测试的环境配置等信息写下来。有些描述性信息是针对“文件”这个层次的,比如测试者的姓名。有些信息可能针对“组”这个层次,比如采集的是“温度”,单位是“摄氏度”。有些信息则可能针对“通道”,比如采集的是发动机哪个部位的温度等等。描述性信息比较利于他人阅读文件,并且,在搜索文件数据的时候,可以派上大用场,可以先利用这些描述性信息进行定位。当然,这些信息最好能和“原始数据”(raw data)放在一起,要是放在两个文件中,一是难以对应起来,而是不利于维护。这也好比是写LabVIEW程序,你写的程序,别人也要能看到,没太多的好办法,就多写点注释吧。

这样的TDM模型也有其缺点。至少看起来有点复杂,同时有原始数据和描述性数据,还要实现那么多的技术要求,着实有点困难啊。其次,这个模型写下来就固定了,一共就3个层次,说到底在某个文件中也就2个层次,不能扩展,不像XML那样方便。我有时候就想要把数据写到一个“通道”中,我还非得先造一个“组”出来(其实可以不写,默认会造一个出来,但是逻辑结构上不能缺少)。还有其他限制条件,比如原始数据必须写在“通道”这个层次,不能写在“组”这个层次等等。

总体来讲,TDM数据模型利大于弊,比较适合测试测量领域的数据的存储,是一套不错的解决方案。

今天谈谈如何选择合适的文件格式。

在LabVIEW中可以使用的文件格式有好几种,争对于测试测量数据的文件格式也不少。每种文件格式都有自己的优缺点,很难说孰优孰劣。关键的问题在于要选择合适自己的文件格式。

那么,在选择具体的文件格式时,有哪些指标可以参考?

1)性能。测试测量数据的一个比较重要的use case就是要一边采集数据一边存储数据,NI现在采集数据的速度已经非常快了,性能的瓶颈往往是在存储数据到文件中去这个步骤上。当然,有些use case对于读取数据的性能也有要求,比如要做实时的数据分析等。因此,在选择合适的文件格式时,需要考虑性能的问题。

2)兼容性。采集数据、存储数据、分析数据,用的可能不是同一套软件,很有可能在不同的平台、不同的软件中完成这些不同的功能。那么就需要采用一种比较通用的文件格式。

打个比方,XML就是一种比较通用的文件格式。

3)支持的数据类型。并不是每种文件格式都支持所有的数据类型。有些可能不支持存储二维数组、不支持存储时间、日期等等,在选择文件格式时需要注意到这一点,以免将来带来不必要的麻烦。

4)是否方便使用。有些人可能喜欢定义一套自己的文件格式,对于高手来讲也未尝不可,但是对于一般的用户就需要考虑是否有这个必要。有些文件格式,在LabVIEW中已经有现成的、丰富的API,那就直接拿来用吧。

5)可维护性、可移植性。写完的文件很有可能将来还会修改,还可能会拿去给别人去修改。别人是否看得懂这样的文件?别人是否方便修改这样的文件?

6)文件大小。存储相同的信息量,当然文件越小越好,信息存储紧凑一点好。

当然还有其他很多方面的指标可以参考。暂时先说这些,以后还会有更深入的内容介绍。

针对于测试测量行业的数据存储,LabVIEW提供了数种不同的文件格式,先来介绍一下LVM格式。

LVM(LabVIEW Measurement File)总体来说是一种比较轻量级的文件格式。它基于ASCII编码,用一般的文本编辑器打开都能看懂。当然,这个特点优劣参半,非二进制代码的文件,总体来说性能较低,并且不够紧凑(即存储相同信息量,文件稍大)。所以,LVM文件格式适用于对性能、文件大小并不具有太高要求的情形。

左图显示的就是用普通的文本编辑器打开一个LVM文件的情形。可以看到

LVM文件还有一个缺点,就是header中的属性是固定的,仅通过LabVIEW的API并不能增加用户自定义的属性,这是一个限制。当然,不排除这样的情况:用户自己用文本编辑器打开LVM文件,向其中写入或者修改一些属性。

世上没有完美的文件格式。LVM文件格式也有其自己的优缺点,有其独特的应用条件。并不能根据某个单一的指标判断它是好是坏,使用时应先判断自己的应用要求,作出合适的选择。

今天先来谈谈Datalog文件,这种文件格式也有点年代了。基本上可以认为这种文件格式是二进制的。准确的讲,如果仔细研究,可以发现这种文件的内部结构比较奇怪。举个例子:如果往这个文件中存储3个int32的数字,用二进制的文本编辑器打开,可以看到内容类似于:

这个还比较还理解,前面是一些头文件,后面是1、2、3三个数字。但是如果写入a、b、c三个字符,情况就比较复杂了:

中间再省略若干行0。。。到文件的最后是:

由此可见,该文件格式对于不同的数据类型、不同的存储方法有不同的内部结构。我个人看来,对于后一种结构,还是有不少的冗余信息的。这种文件使用起来也不是太复杂,有一整套的API可以调用,具体的使用方法可以参考帮助文档。

总体来讲,这种文件格式,性能、使用的建议度、可读性均在中等水平,仅适用于LabVIEW软件。对于性能有一点要求,但要求不是很高的用户来说,可以采用该文件格式。

再介绍一种文件格式,在LabVIEW中就叫做“二进制文件(binary file)”,其实很多文件格式都是二进制的,包括刚才介绍的Datalog,以及以后要介绍的TDMS。为了区别于其他二进制文件,我们有时候叫这种二进制文件为“bytestream”。具体操作这种文件格式的API非常简单。

这种文件格式的性能非常高,使用起来也非常方便(就两个VI,一个负责写,一个负责读),但是数据的组织,也就是内部数据的结构(在这里无法透露具体的内部结构),可以说是比较差的。如果用户对于写入文件的性能要求比较高,但是并没有太多后续维护、管理数据的需求,可以考虑采用这种文件格式。接着介绍LabVIEW中的另外两种文件格式。首先是Bytestream。

这个文件格式说穿了就是二进制文件。就两个VI,分别是读和写。基本支持LabVIEW中的任何类型的数据。只要你在LabVIEW中能造出的数据,都可以用这种文件格式存储。可以猜测,其实这两个VI做的事情也比较简单,直接把LabVIEW在内存中的这部分数据写到文件中就行了,当然这样做的话,效率也比较高,因为没什么运算的步骤。但是也有部分缺点,比如直接把数据写到文件中也不见得好,真正的问题是如何管理这些数据。例如,读文件的时候也需要知道究竟这些文件存储了什么类型的数据,究竟存储在文件的什么位置等等。

总的来说,如果用户追求纯粹的写文件的速度,并且不在乎将来读文件是否遇到困难(其实如果一个文件只写不读那就没什么意义了),那么用这样的文件格式还是可以的。

接下来介绍TDM文件格式。

TDM文件是指后缀名为.TDM的文件。文件的逻辑存储模型遵循NI的TDM Data Model,三层结构。TDM文件主要分为两个物理文件,一个是主文件,后缀名为TDM,存储原始数据以及属性等信息;另一个是头文件,后缀名为TDX,主要存储属性信息,方便查找,作为一个索引文件。主文件是类似于XML结构的,而头文件是一个二进制文件,理由也很简单:头文件主要用来索引搜索数据,所以对读的速度有较高要求,因此作为二进制文件更合适。

对于TDM文件的操作,LabVIEW中主要通过Storage VIs来完成。TDM 的文件格式,我个人感觉,最大的优点在于对于数据的管理。以前介绍的文件格式,没有对数据的管理做太多的考虑。TDM文件格式分为三次结构并且可以加

入用户定制的属性,使用更为方便。举个通俗易懂的例子:很多人中午要带饭,放在饭盒里。普通的文件就是一个大杂烩,饭、菜混合放在一起,吃起来不方便并且看上去就杂乱;而TDM文件就像是有分隔的饭盒,饭菜可以分开放置,方便整洁。

随着NI在测试测量文件方面的进步,TDM的文件格式已经逐步被TDMS 文件格式取代,下次专门介绍TDMS。

终于写到TDMS了,千呼万唤始出来啊,其实所有前面的相关文章都是为了TDMS作铺垫。正是由于用户提出的种种需求以及其他种种文件格式的缺点,才有了TDMS的出现。

1. TDMS文件的逻辑格式

TDMS文件的逻辑格式遵循TDM三层结构,仍然是文件、通道组、通道三层。用户在使用时只需要关心这三层就行了。

2. TDMS文件API

TDMS文件格式基本上可以称为NI用在测试测量领域的通用数据文件格式,LabVIEW, CVI/LabWindows, Signal Express, DIAdem中都可以使用,也常看到在Excel, MatLab被中调用。TDMS最核心的内容都在一个dll中,用户如果安装了LabVIEW,就会发现在Program Files\National Instruments\Shared\TDMS文件夹中有个tdms.dll的文件。其他软件正是通过调用这个dll的API来操作TDMS文件的。

在LabVIEW中操作TDMS文件其实相当方便,有专门的TDMS面板,提供了TDMS绝大多数的功能。虽然我们一直说Write/Read Measurement Files, Storage VIs, TDMS分别面向初级、中级、高级的用户,但是我个人觉得LabVIEW中的TDMS用起来十分方便,即便是初级用户,也能很容易的上手。在面板上一共就10个SubVI,无论是什么样的数据类型,都可以用这样同一套SubVI,无需大量额外的编程工作。

这里可以简单介绍一下TDMS面板上的两个SubVI,我个人觉得十分有用。一个是“TDMS File Viewer”,当用户写完某个TDMS文件之后,就可以用这个SubVI来方便的查看文件的内容,只要输入TDMS文件的路径即可,运行VI 就会跳出一个Viewer的界面,可以查看数据、属性,并且可以根据数据简单的绘制出一些波形图。另外一个是“TDMS Defragment”,通常用户写完TDMS 文件之后,可能会发现这个文件非常大,那么这时就可以使用这个SubVI,可以大幅度的减小文件的size。

3. TDMS二进制文件

TDMS从设计之初就确定它必须是二进制的。二进制文件带来两个优点:第一,与一般的文本式文件相比,二进制文件通常比较小;第二,二进制文件读写通常比较快。这两个都是其他二进制文件都具备的优点,就不再多说了。

4. TDMS头文件

用户写完TDMS文件之后,会发现硬盘上其实有两个TDMS文件,一个是.tdms,另一个是.tdms_index文件,我们通常把前者称为主文件或者数据文件,而把后者称为头文件或者索引文件。头文件与主文件相比,最大的区别就是把主文件中的raw data都去掉了,只留下属性等信息。这样做,有两个目的,第一,可以使得读文件加快速度,并且支持随机读取文件数据,这个稍后再解释,用户看完后面的内容就可以理解。第二,可以使得某些软件的搜索TDMS文件功能加快。比如在DIAdem中搜索TDMS文件,可以根据文件名、通道组名、通道名(其实这些也是属性),或者其他某些属性进行搜索,这个时候,仅将TDMS的头文件载入进行搜索,其速度远远比将TDMS主文件载入搜索快得多。

5. TDMS的内部结构

TDMS文件的内部结构,也就是物理结构,可以在这里找到原文。一般的用户并不需要了解这方面的知识就可以方便的使用TDMS文件。在这里介绍这个内部结构,是为了更好的解释TDMS文件格式的优点。

TDMS内部结构的核心概念是segment,如下图。为了避免混淆,在这里必须澄清的是,这个segment的概念与TDM的三层结构(即逻辑结构)没有任何对应的关系,也就是说,一个通道可能对应着多个segment,一个segment 中也可能有多个通道。segment是什么意思?我们在写TDMS文件的时候,数据本来可能存放在内存中,那么总要往硬盘上写这些数据的,每次往硬盘上写(flush to disk)就会产生这样一个segment。同样,我们在读TDMS文件的时候,也是一个segment一个segment的把内容读出来。

再稍微深入介绍一下这个segment中的内容。一开始有一些头信息,比如这个segment中是否含有meta data,是否含有raw data,version是多少。下面的东西就很重要了,有个“next segment offset”的信息,指向下一个segment的起始位置,这个有什么用呢?比如我要读某个通道的数据,发现这个segment中并不包含这个通道的内容,就可以使用这样的信息直接跳到下个segment中看下个segment是否有要找的信息。同样,还有一个“raw data offset”的信息,比如用户只想读raw data,并不关心属性之类的信息,那么这个“raw data offset”的信息就派上用场了。说到这里,就可以明白,TDMS是怎样支持Random access,怎样支持独立的读属性信息和raw data的信息。

此外,这个segment还有一个极为重要的特点。我们每次写数据,每次往TDMS文件中flush to disk的时候就在文件的后面添加这样一个segment,而不去关心之前的segment中包含了什么样的信息。这个特点非常关键,这就可以使得我们写文件的速度非常快,我们并不关心之前文件中包含了什么信息,也就使得我们写TDMS文件的速度并不和TDMS文件的大小成正比或者有任何关系。

6. TDMS文件格式的优点

我在以前的文章中提到几个数据文件格式的技术要求,我们现在再来回顾一下,看看TDMS文件是如何实现这些技术要求的,这样也就能看出TDMS文件的优点来。

1)写文件速度必须要快——通过segment实现以及二进制。

2)向文件追加(append)数据的时候,速度要快——segment。

3)写文件的速度不能与文件大小成正比——segment。

4)支持随机的读取——segment以及头文件。

5)支持分别读写描述性信息和原始数据——segment以及头文件。

6)对读文件的速度也有一定的要求——segment以及头文件。

7)文件不能太大——二进制。

7. 其他

TDMS文件格式目前(LabVIEW 8.5)只支持Windows和PharLap(一种实时操作系统)平台上。不过我还看到一个基于VI的TDMS API,这个完全基于LabVIEW,既然LabVIEW能在其他平台上工作,那么这个小工具也能在其他平台上工作。当然,效率、性能的会差很多了。

通常总有人拿TDMS文件格式和一般的基于Windows API文件流操作比较,然后会说TDMS比那样的Win32 streaming API慢嘛,是不是TDMS不行?比如在某些磁盘阵列的配置下,Win32 streaming API可以达到

650MB/S,而TDMS只能600MB/S左右。我在这里需要澄清的是,TDMS 在保持着数据良好逻辑结构(TDM的三层结构)、良好的数据管理的前提下,还能保持着这样高速的性能,这才是TDMS最大的优点。Win32 streaming API 只是纯粹的追求速度(也仅比TDMS快5-10%左右),并不能将测试测量的数据良好的组织好、管理好,用户如果片面的追求速度而不管写入文件的数据如何保存如何管理,那就有点得不偿失了。

当然,TDMS文件也并不完美,同样存在着种种缺点。比如不能支持方便的删除某个通道的功能,目前还不支持其他操作系统等等。相信将来都会有改善的。

最后,用一个不是很恰当的例子来结束这篇文章。测试测量数据的文件格式,有很多种,文件格式就像我们中午带饭的饭盒一样。其他的数据文件格式就是把饭菜都放在一起,吃起来不方便(速度慢),而且味道都混杂在一起(组织不好);而TDMS文件格式就像是内部有分隔的饭盒,不同的饭菜分开存放,吃起来又方便(速度快)味道又好(组织良好)。

labview事件结构学习

labview事件结构学习 编程的主要目的是为了实现用户的某种功能,用户通过用鼠标、键盘、程 序内部等触发某种程序动作,从而达到某种结果,这些操作都被称作为事件,LabVIEW 中相应这些事件最常用的结构就是事件结构。事件结构内容丰富,基 本上大的程序结构都需要用到事件结构,下面将详细介绍事件结构。事件结构 在程序不能够单独响应各种事件,必须与循环结构一同使用,如下图事件添加 方式很简单,鼠标右键事件框弹出菜单如上图,有添加、删除、复制、编辑事 件等选项,按照操作即可。如下图,为事件结构添加Stop 事件,布尔控件触发 事件的方式有多种,鼠标按下、经过、离开、进入等,这里我们选择值改变。 确定后,stop 事件就被添加进去了,如下图,当我们运行程序后,点击前面板 的stop 按钮,触发事件使while 循环停止而后程序也停止。同一事件分支只能 添加一种事件吗?当然不是!有的时候有很多不同操作却会执行相同代码,怎 么编程才不会让代码冗余呢?看个例子,如下图2 个按钮stop1,stop2 点击后 都可以让程序停止,我们怎么为其添加事件呢?我们先添加一个事件stop1 的,方法上面已经描述了。由于stop2 的执行代码和stop1 一样,我们在事件stop1 上右键->弹出菜单->编辑本事件分支(Edit Event Handled by This Case)会弹出已添加事件stop1 的编辑框,这是左侧有2 个按钮如下截图我们点击Add Event 左侧事件列表会出现如下变化选中这个后,右侧列表选中stop2 的Value Change 事件后,点击确定在看该事件分支如下,2 个事件就添加在同一个分支当中了,运行程序后,点击stop1 或stop2 均可让程序停止。超时超时是事件结构特有的,看名字就知道是怎么回事,即超过一定时间没有触发事件则执行超时 事件。如果超时时间设置所以如果程序事件功能不多,又需要定时执行一段代码,可以考虑用此方式来完成;如果程序操作频繁,则不建议用此事件来定时

Labview执行结构:详细说明

执行结构:详细说明 While循环 与文本编程语言中的Do循环或Repeat-Until循环类似,必须满足特定条件之后,While循环才会执行其内的程序代码,如图1所示。 图1. LabVIEW中的While循环;具备While循环功能的流程图; 还有While循环功能的伪码范例 While 循环位于Structures面板上。从面板上选择While Loop之后,针对所要重复的代码区块,可用鼠标拖拽出矩 形并将之圈住。放开鼠标之后,即会有While循环圈住用户所选的区块。 只要将对象拖拽至While循环中,即可将其新增至While循环中。 只要条件接线端接收特定的布尔值之后,While循环随即执行代码 也可通过While 循环的条件接线端来处理基本错误。若将错误簇连接至条件接线端,则只有Status参数的真或假值传送至接线端。同样,Stop if True和Continue if True快捷菜单项目,将分别变更为Stop if Error和Continue while Error。 计数接线端属于输出端点,其中包含已完成的循环次数。 While循环的循环计数均从零开始。 注意: While循环将至少执行一次。 无限循环 无限循环为常见的程序错误,即无法停止的循环。若条件接线端 i为True时停止,而用户又在While循环外部放置布 尔控件接线端。一旦循环开始,控件值即成为FALSE,就会形成无限循环。

图2.While循环之外的布尔控件 因为在循环开始之前,仅读取该值一次,所以改变控件的值并无法停止无限循环。若要通过控件停止While循环,则必须在循环中配置控件接线端。若要停止无限循环,则按下工具栏上的Abort Execution按钮,即可终止该VI。 在图3中的While 循环将不断执行,直到随机数函数的输出大于或等于10.00,且Enable控件为TRUE时才会停止。当且仅当“与”函数的两个输入都为真时,函数的返回值才为真。否则,与函数将回传FALSE。 在图3中,只要随机函数不产生10.00以上的值,就会成为无限循环。 图3.无限循环 结构隧道 隧道负责为结构传送数据。 While循环边框上的实心区块即为隧道。此区块的颜色与隧道所连接的数据类型的颜色相同。在循环终止之后,随即有数据送回循环。当隧道传送数据进入循环时,只有数据抵达隧道之后,才会执行循环。 图4即以计数接线端连至隧道。直到While 循环执行完毕,隧道中的数值才会传送至Iterations显示控件。计数接线端在Iterations显示控件中只会显示最后的数值。 图4. While循环的隧道

labview控制程序流程——labview事件结构

labview控制程序流程——labview事件结构 1 事件结构及它的图形化表示法事件被用来通知用户有异步活动发生。图 形化语言的事件响应包括:用户界面事件、外部I/O 事件和程序其它部分的事件。对事件的处理程序也被称为:事件驱动程序。事件驱动程序可以分为若干 个分支,每个分支处理不同的事件响应。所以对事件的响应结果也可以控制程 序的流程。事件驱动机制来自于可视化的操系统,可视化操作系统对用户事件 提供了简洁、有效的响应方式,最常见的事件来自于鼠标和键盘。虚拟仪器借 助于操作系统的事件处理机制实现了图形化语言的事件响应能力。在没有引入 事件结构之前,LabVIEW 是借助于轮询的方式来查询用户操作,由于轮询的方 式会占用一定的CPU 资源,甚至可能遗漏事件,所以这种处理方式并非理想。事件结构的出现避免了对CPU 资源的占用,同时也避免了事件的遗漏。事件 结构在函数选板》编程》结构子选板中可以找到,并可以将其直接拖拽到程序 框图中,图形化表示的事件结构,参见下图。图 1 图形化的事件结构与Case 结构和循环结构类似,事件结构也包含了一个主框架,这个框架内将用来放置 事件处理的事件驱动程序代码。如果事件处理任务众多,会有众多事件分支存在,在结构上类似Case 的多帧结构(选择器标签)。当在程序框图上拖放一个 事件结构时,我们只能看到上图所示的一帧已经预先注册的超时事件(Timeout),超时事件分支。它具有定时延迟的基本功能(不包括While 循环),参见下图。图 2 具有定时延迟的基本功能当然也可以采用另一种表示方法,参 见下图。图 3 利用事件结构内部节点获得中止时间通过这个例子也好理解内部 节点中时间的含义(是事件响应的停止时间)。超时事件超时事件是一种特殊 的事件,当然也可以看成是默认的事件分支。如果存在其它事件源时,超时事 件完全可以被忽略或取消。看下面一个例子。图 4 仅有的两个事件之一超时事

LabVIEW事件结构的妙用

LabVIEW事件结构的妙用 首先,我们回顾一下上期节目:LabVIEW网络讲坛乊悬案迷思中关于事件结构的几个重要知识点。 事件结构的基本组成部分: 事件结构五大基本组成部分 事件结构由——事件选择器、超时接线端、事件数据节点、事件过滤节点和动态事件接线端5个基本部分组成。 事件结构编程的3条黄金原则: 在使用LabVIEW事件结构迚行编程的时候,我们应该注意:1.不要将事件结构放置在while循环乊外,而应该放置在while循环的内部;2.不要在事件结构的内部使用循环处理事件,可选择采用生产者消费者结构,在生产者循环中放置事件结构,在消费者循环中处理事件;3.记得为事件结构添加一个单独处理停止按钮的分支。 遵守以上三条原则将使我们的程序更加健壮,避免在使用事件结构的时候出现前面板死锁等问题。 过滤事件与通知事件:

在LabVIEW中,以问号结束的事件被称为过滤事件,其余的事件被称为通知事件。对于通知事件,程序可以感知事件的发生并且响应该事件,然后再处理在事件结构中定义的任务;而对于过滤事件,程序感知事件发生后,首先处理在事件结构中定义的任务,然后根据事件过滤节点的值(Discard?)来决定是否响应该事件或是否改变事件数据。 因此我们建议,在希望参与处理用户操作时使用过滤事件,因为过滤事件可以放弃事件或修改事件数据。如果仅需要知道并响应用户执行的某一特定操作,则应使用通知事件。 在本期节目中,我们着重介绍动态注册事件的用法。 静态和动态两种事件注册模式: 静态注册指定了事件结构的每个分支具体处理哪些事件。一旦VI开始运行,LabVIEW将自动注册这些事件,并且在VI运行的整个过程中无法改变事件结构所处理的事件。 而动态事件注册与VI服务器相结合,允许在程序运行时使用控件、VI或应用程序的引用来动态地指定和改变产生事件的对象。动态注册在控制LabVIEW产生何种事件和何时产生事件等方面更为灵活。 Demo 1和Demo 2帮助大家更好地理解动态注册事件编程方法。 Demo 1:动态注册事件_阿拉丁神灯.vi Demo概述: 在这个VI中,用严格自定义的方式将一个布尔类型的控件做出神灯的样子,并为这个布尔控件动态注册了”鼠标按下”的事件。这个事件执行的任务是显示神灯神仙,并弹出一个对话框。由于该事件采用的是动态注册的方式,所以可以通过一个按钮取消对该事件的注册。并通过另一个按钮再次注册该事件。这就是动态事件的使用效果,它可以在程序运行的过程中,动态地控制何时注册事件和注册什么样的事件。 程序实现:

labview事件结构浅析

https://www.360docs.net/doc/5e12533927.html,/forum.php?mod=viewthread&tid=207837 使用LabVIEW图形化语言开发的应用程序界面是图形化用户操作界面,也称为:GUI (graphical user interface),它的作用是与操作者实现人机对话形式的互动操作。这种对界面操作的互动响应在LabVIEW 6.1发布之前,只能是通过“轮询(polling)”的方式来实现。轮询的方式的缺点是:需占用一定的CPU资源(在没有事件发生时)和灵活性不好。在LabVIEW6.1引入事件结构(Event Structure)后,采用事件结构来设计、实现的GUI操作则变得更加灵活、方便,并且不占用CPU的资源,这与先前采用轮询的方式来查询事件的方式相比要合理的多。下面结合应用项目中的设计实例来介绍GUI设计中的事件驱动。 有关事件结构的一些基本概念、原理及使用方法在LabVIEW Help及许多中文书中都作了详细的讲解,这里我就不作更多地介绍了。 事件结构通常包括以下部分: 1、Event cases——包含有若干个注册的事件源及同等数目的Event case层,在每个Event case层中包含对该事件响应的处理程序。 2、While循环——用来检测连续不断产生的事件 事件结构中的While循环,是用来确保检测到连续不断发生的事件。如果没有这个While循环,无论有多少事件发生只能对第一个发生的事件进行处理,处理完后程序将退出事件结构。 菜单选项事件结构实例 2011-11-11 09:50 上传下载附件(8.79 KB) NI USB-9219是一款4通道通用C系列模块,专为多功能测试而设计。USB-9219能够测量传感器中的多种信号,如压力计、RTD、热电偶、测压元件和其他需要供电的传感器。由于通道接受单独选择,4条通道可以分别进行不同类型的测量。测量范围随测量类型而异,包括±60 V最大电压范围和±25 mA最大电流范围。 第1步、创建一个项目:综合参数测量仪 按照我的设计习惯,首先在桌面上创建一个新的文件夹,命名为《综合参数测量仪》。然后,打开、运行LabVIEW开发环境,并选择开发环境中的:新建》项目。 此后,在“项目浏览器”就可以看到一个新建的项目:"未命名项目1"。单击项目浏览器:文件》保存,并将该项目命名为:“综合参数测量仪”后,存放到桌面上的《综合参数测量仪》文件夹中。 此时,项目创建完毕。 第2步、创建一个主vi:综合参数测量仪.vi 2011-11-11 09:41 上传下载附件(14.71 KB) 打开刚刚新建的“综合参数测量仪”项目,然后用鼠标右击该项目中的”我的电脑“选择:新建》VI,即创建了一个新的vi。 用鼠标点击新vi的:文件》保存(命名为:综合参数测量仪.vi)。 主vi即宣告创建完毕。如例图所示。

LABVIEW 中的事件结构杂谈

LABVIEW中的事件结构杂谈 刚开始接触事件结构时觉得它很好用,所以很喜欢用,但也引起了一些问题,就是前面板很容易就被挂起来了,就是所前面板没有响应了,很郁闷。之后就不敢用了,很多可以用事件结构的地方都只用CASE结构麻烦的代替了~~ 今天被师兄那么一指点,觉得完全是委屈了事件结构啊,之前事件结构引起的问题可以很容易的解决。 方法就是设置“超时”(之前一直觉得这个东西没用的): 一般情况下,事件结构是会和while循环套用的,通过不断的循环来执行不同事件源激发的事件,但如果不设置超时,也没有事件源发生,那么while循环将一直等待事件的发生而不进行循环,这样就会使得事件结构外的其他程序也不能执行,可能造成的结果就是前面板本该有反应的地方(比如变量值的变化)没有了反应。 而如果设置了超时,比如设置为100(ms),意思就是每隔100ms如果没有事件发生就超时,进行一次循环,那么事件结构外的其他程序也就得到了执行。 总结一下: 如果事件结构在while循环中,而事件结构之外又有其他的程序需要执行(可能不依赖于事件的发生),那么就应该设置超时。 在事件处理过程内,如何响应前面板命令控件的命令? 我发现,在一个事件内的处理过程完成之前,系统不能响应前面板的其他命令。系统是在事件完成之后的等待时期才响应其他前面板命令事件。 编辑事件结构对话框的下边有一个: 锁定前面板在事件分支执行完毕前。你可这个默认选中的选项取消了,就可以实现你的“在一个事件过程处理中途响应前面板的其他命令"功能。 LabVIEW事件结构 使用LabVIEW图形化语言开发的应用程序界面是图形化用户操作界面,也称为:GUI (graphical user interface),它的作用是与操作者实现人机对话形式的互动操作。这种对界面操作的互动响应在LabVIEW 6.1发布之前,只能通过“轮询(polling)”的方式来实现。轮询的方式的缺点是:需占用一定的CPU资源(在没有事件发生时)和灵活性不好。在LabVIEW6.1引入事件结构(Event Structure)后,采用事件结构来设计、实现的GUI操作则变得更加灵活、方便,并且不占用CPU的资源,这与先前采用轮询的方式来查询事件的方式相比要合理的多。下面结合应用项目中的设计实例来介绍GUI设计中的事件驱动。 有关事件结构的一些基本概念、原理及使用方法在LabVIEW Help及许多书中都作了详

labview课程设计模拟计算器事件结构

河北工程大学 《虚拟仪器设计》课程设计报告 课题:计算器模拟 姓名:张振兴 学号: 090030301 班级:测控三班 完成日期:2012 年 6月19日

目录 一、设计思路 (2) 二、实现过程 (2) 1、面板键入感应 (2) 2、运算变量的初始化 (2) 3、无操作时的默认输出 (3) 4、数字的键入1-9的输入 (3) 5、数字0的输入 (4) 6、小数点的键入 (5) 7、结果去零操作 (5) 8、“+/-”键的设计 (7) 9、“+、-、*、/”四则运算 (7) 10、等号键 (8) 11、开方运算 (9) 12、取倒数倒数运算 (9) 13、退格键CE的设计 (10) 14、清零键C (11) 15、停止键OFF (12) 三、整体程序 (12) 四、前面板的设计排版 (12) 五、while循环中寄存器能 (13) 六、此计算器可以实现的功能 (13)

一、设计思路 完成标准型计算器的一般功能。 输入第一个数,进行存储并显示输入运算的类型并存储输入第二个数,存储并显示按“=”或则按其它运算符号“+、-、*、/”进行连续的运算,最后显示运算结果。 二、具体的实现过程 1、面板键入感应 在前面板上建立22个布尔量,其中包括0--9十个数字键,1个小数点键,4个“+、-、*、/”运算键,1个等号键,1个开方键,1个符号转换键,1个倒数键,1个清零键,1个退格键,1个退出键。如下图所示: 2、运算变量的初始化 在运行程序之前,首先对需要用到的变量进行初始化,如图所示

3、无操作时的默认输出 当键盘上的键没有任何一个按下时,系统仅执行顺序结构第一帧,系统处于初始化状态输出。 4、数字1--9的输入 以数字“1”为例,当按下数字“1”后,布尔量为值改变,进入时间结构结构,将1输出到显示中,布尔量再次改变时。(图1.4.1)若再次输入1,为避免出现01这样的字符串,先判断之前显示的数据是否为0,若为0,则直接输出1,(图1.4.2)若不为0,则将这两次输入的数据通过

labview事件结构

最近贴子比较少啊,发个贴子讨论一下基于事件结构的状态机吧,最近好像不少朋友都会有这方面的问题。 有些截图看不清文字的可以单击图片放大来看。 我感觉在LabVIEW中进行程序框架设计,似乎只见到过一种框架,那就是状态机,(并行的算不算?)还有“主/从设计模式”、“生产/消费模式”之类的,但好像也是建立在状态机的基础上的。如果真是这样的话,状态机就成了唯一的程序框架了?状态机简单一点说就是上一个运行状态决定下一个运行状态,在LabVIEW中有标准的状态机的模板,菜单中选择文件>>“新建…”(是第二个而不是第一个“新建”,注意“新建”二个字后面的省略号,表示会弹出界面来),在弹出来的对话框中的右边树形控件中选择“VI>>基于模板>>框架>>设计模式>>标准状态机。(还有其它一些设计模式也可以这样打开)新弹出的标准状态机如下图: 我一开始的时候看到这种结构不是很好用,感觉有点怪,完全不需要用户进行操作整个程序就运行完了,所以刚听到状态机时感觉这种结构的功能也没有宣传的那么强大,我一般在主程序中都没有使用这种结构,只是偶尔在一些比较底层的子VI里使用一下,因为这种结构跟顺序结构差不多,但在调试、查看时又没有顺序结构直观,要在不同的CASE进行切换比较麻烦,虽然这种结构在错误处理上有一定的优势。后来又发现,说到状态机的话,是说这样一种编程思想,好些类似的结构似乎都可以归到状态机范畴里面(难怪官方只说这种是标准状态机?)其它状态机如下: 第一种我是用得比较多一点——基于事件的状态机

这种结构充分发挥了用户与程序的互动,比如上图,用户在点击前面板的“开始采集”按钮后才会开始进行数据采集任务。我一般在主程序上是用这种结构,一些附加功能,比如用户设置、生成报表等功能都是利用事件结构处理前面板的按钮点击事件来实现的。 第二种跟标准状态机也差不多: 这种结构是利用循环结构里面的循环计数器来选择需要执行的下一个状态。也是不需要与用户进行互动而一直执行的,在一些固定测试顺序的测试中看到过这种结构。状态机中使用到了循环结构,而循环结构中另一个非常实用的东东就是移位寄存器(事实上状态机也是借助了移位寄存器才能更好地实现它的功能),将上一次(或几次)循环的数据“移到”本次循环中进行使用,刚开始学LabVIEW的时候不怎么敢用移位寄存器,但一旦开始使用后,就发现移位寄存器好处实在是不少,如果还不会使用的话写一二个小程序,立马就可以发现,其实移位寄存器也很简单:上面的程序中使用高亮执行的话就可以很清楚地了解移位寄存器的作用了。 有了移位寄器器,再回头看一下上面的基于事件的状态机,这种结构还不够完善,因为有时需要在用户没有点击按钮的动作的时候也要执行某些程序,比如如果用户多长时间没有动作就向串口发送一些信号之类的,或者用户触发某些事件后要将结果显示出来,

event提高:LabVIEW事件结构编程

LabVIEW事件结构编程 事件驱动的编程允许用户通过前面板的操作,或是其他的异步事件来驱动LabVIEW程序的运行。事件是一种异步的信号,告知PC有事情发生。用户界面、外部I/O或是程序的一部分代码都有可能导致事件的发生。使用事件结构可以实现仅当事件发生时,程序才需要响应,别的时候程序可以处理其他迚程或是其他的事件,事件结构相当于一种“中断”。相对的,如果不使用事件结构,程序会以“轮询”的方式来检测事件的发生,但这样会大大消耗CPU的使用时间,不利于处理复杂、多线程的程序。因此,事件结构允许将CPU的使用降低到最小,但又不牺牲与用户的交互性。用户界面事件:鼠标点击、键盘操作等等外部I/O 事件:硬件定时、硬件触发、或是硬件出错等等。其他程序事件:程序间的通讯等注:LabVIEW支持用户界面事件和程序事件而不支持外部I/O事件。 1. 事件结构 典型的事件结构如图1所示。事件结构包括一个或多个子程序框图,或事件分支,注意每当结构执行时,仅有一个子程序框图或分支在执行。事件结构的执行过程是,一直等待直至某一事件分支的事件发生,然后执行相应事件分支从而处理该事件。右键单击结构边框,可添加新的分支并配置需处理的事件。为事件结构边框左上角的“超时”接线端连接一个值,以指定事件结构等待某个事件发生的时间(以毫秒为单位)。默认为–1,即永不超时。 图 1事件结构

用户界面事件分为消息事件和过滤事件两种。 a.消息事件 消息事件指一个用户的行为已经发生,使用消息事件来反馈一个已经发生的事件,并且LabVIEW已经对它迚行了处理。例如,“鼠标按下”就是一个消息事件,图2中的事件结构的分支程序实现了用户用鼠标点击停止按钮,按下后停止程序的功能。这个事件是在用户释放鼠标以后LabVIEW迚行处理的。 图 2 消息事件 b.过滤事件 过滤事件在用户行为发生之后,LabVIEW处理该事件之前先告知用户,由用户来决定程序接下来如何处理事件,有可能处理的方式与默认的处理不同。过滤事件有什么好处?使用过滤事件以后,用户可以随时按需要修改程序对事件的处理,甚至可以完全放弃该事件,而对程序不产生影响。例如:“前面板关闭?”就是一个过滤事件(过滤事件后面都有一个?)。图3中的事件结构实现放弃对“前面板关闭?”这一事件的响应,从而将这一事件过滤。

labview深入探索xcontrol

labview深入探索----xcontrol control是LABVIEW8.x新增的功能,LV中的CONTROL我们是再熟悉不过了,这个"X"到底代表什么那,到NI网站上也没找到它的英文定义,可能相当与ACTIVEX中的"X"?虽然无法弄清楚它的定义,但是它的作用是清楚的,我个人理解它更象VC中MFC的控件自画,也具备了一些ACTIVEX的能力,与ACTIVEX的最大区别是ACTIVEX是独立于平台的,可用于各种编程环境,从这点来说,可以把它看做LV内部的activex,MFC中的控件自画是这样的,当我们要做一个特殊形状的控件时,可以设置它的一个属性是自画,own draw,也就是说,这个控件是用户自己画出来的,比如一个按钮,当鼠标进入它的控制区域,会自动显示凸起状态,还可以自动改变颜色,IE菜单就是这样,当鼠标移入的时候,背景色自动变成兰色,离开后,又自动恢复,实际上,它是在响应两个事件,MOUSE_ENTER 和MOUSE_LEAVE事件. 在xcontrol出现以前,我们也可以对一个控件通过属性节点和事件结构实现这种动态变化,但是有着本质的区别,xcontrol通过事件结构判断事件,利用属性节点改变其显示方式是完全在内部实现的,因此它是可以重用的,从使用方法上它和LV一般的控件没有任何区别,我们完全可以把它看成LV又给我们提供了新的控件,我的文章里多次提到AE的概念,有了XCONTROL,我们不但可以保存数据,而且有了显示的能力,所以说,对于基于组件编程的LV,能力有了很大的提高. 虽然xcontrol是一个新增的特性,但是它的制作方法实际上我们或多或少地都涉及到了,这就使得制作XCONTROL变得相对容易了.

LabVIEW程序设计模式(四)—状态机和事件结构的结合

LabVIEW程序设计模式(四)—状态机和事件结构的结合 上两节分别解决了基本状态机的第(1~5)个问题,但是是否具备一种模 式能够综合队列型状态机模式和用户界面事件型模式的优点呢?这样可以同时 避免基本状态机的第(1~5)个问题。答案是肯定的,本节将介绍如何将状态 机与事件结构结合起来形成一种新的、稳定的模式。状态机模式的基本构成元 素是while 循环和case 结构,而事件结构模式的基本构成元素是while 循环和event 结构,因此新的模式应该由while 循环、case 结构和event 结构组成。而while 循环的目的是为了保证程序的持续运行,因此必须在最外层,这样就只 剩下了图20 所示的两种组合方式。在第一种方式中,每次循环的运行需要经过一个事件结构才能够实现case 中各个分支的运行,那么到底需要多少个分支呢?一般而言不同的事件都会有不同的事件处理函数(这些函数可以在case 结构中共用),显示这是无法满足要求的,它从本质上而言仍然是一种事件结构。在第二种方式中,程序的主体是一个状态机结构,不同的是在某一个状态分子 中有一个事件结构。我们可以回忆状态机模式中的空闲Idle 状态,这正是长时间占用CPU 资源的源头,如果在Idle 中加入一个事件结构后就有效地规避了 这个问题。图20 三种结构的组合方式因此图20 中的第二种结构综合了状态机和事件结构的优点,有效地克服了基本状态机的第(1~5)个问题。此外, 在【应用2_自动贩卖机】例程中,按钮1USD、2USD 和5USD 的作用是相同的,唯一不同的是它们的代表的币值不同。如果我们希望系统共用币值相加这 个功能,即当这三个按钮任何一个被按下后都调用同一个函数(该函数的功能 是将系统中原来的货币值与新加入的币值相加得到新的值)。这样,需要有一 种途径把1USD、2USD 和5USD 代表的币值作为参数传递给函数。图21 所示为带参数的状态机结构,在消息队列的状态机模式中,加入了一个变体型的变

相关主题
相关文档
最新文档