第一章 虚拟仪器及 LabVIEW 入门
1,1 虚拟仪器概述
虚拟仪器( virtual instrumention)是基于计算机的仪器。计算机和仪器的密切结合是目前仪器发展的一个重要方向。粗略地说这种结合有两种方式,一种是将计算机装入仪器,其典型的例子就是所谓智能化的仪器。随着计算机功能的日益强大以及其体积的日趋缩小,这类仪器功能也越来越强大,目前已经出现含嵌入式系统的仪器。另一种方式是将仪器装入计算机。以通用的计算机硬件及操作系统为依托,实现各种仪器功能。虚拟仪器主要是指这种方式。下面的框图反映了常见的虚拟仪器方案。
虚拟仪器的主要特点有,
null 尽可能采用了通用的硬件,各种仪器的差异主要是软件。
null 可充分发挥计算机的能力,有强大的数据处理功能,可以创造出功能更强的仪器。
null 用户可以根据自己的需要定义和制造各种仪器。
虚拟仪器实际上是一个按照仪器需求组织的数据采集系统。 虚拟仪器的研究中涉及的基础理论主要有计算机数据采集和数字信号处理。目前在这一领域内,使用较为广泛的计算机语言是美国 NI 公司的 LabVIEW。
虚拟仪器的起源可以追朔到 20 世纪 70 年代,那时计算机测控系统在国防、航天等领域已经有了相当的发展。 PC 机出现以后,仪器级的计算机化成为可能,甚至在 Microsoft 公司的 Windows 诞生之前,NI 公司已经在 Macintosh 计算机上推出了 LabVIEW2.0 以前的版本。
对虚拟仪器和 LabVIEW 长期、系统、有效的研究开发使得该公司成为业界公认的权威。
普通的 PC 有一些不可避免的弱点。用它构建的虚拟仪器或计算机测试系统性能不可能太高。目前作为计算机化仪器的一个重要发展方向是制定了 VXI 标准,这是一种插卡式的仪器。每一种仪器是一个插卡,为了保证仪器的性能,又采用了较多的硬件,但这些卡式仪器本身都没有面板,其面板仍然用虚拟的方式在计算机屏幕上出现。这些卡插入标准的 VXI
机箱,再与计算机相连,就组成了一个测试系统。 VXI 仪器价格昂贵,目前又推出了一种较为便宜的 PXI 标准仪器。
虚拟仪器研究的另一个问题是各种标准仪器的互连及与计算机的连接。 目前使用较多的是 IEEE 488 或 GPIB 协议。未来的仪器也应当是网络化的。
1,2 LabVIEW 是什么?
LabVIEW( Laboratory Virtual instrument Engineering)是一种图形化的编程语言,它广泛地被工业界、学术界和研究实验室所接受,视为一个标准的数据采集和仪器控制软件。
LabVIEW 集成了与满足 GPIB,VXI,RS-232 和 RS-485 协议的硬件及数据采集卡通讯的全部功能。它还内置了便于应用 TCP/IP,ActiveX 等软件标准的库函数。这是一个功能强大且灵活的软件。利用它可以方便地建立自己的虚拟仪器,其图形化的界面使得编程及使用过程被测对象信号调理数据采集卡虚拟仪器面板数据处理都生动有趣。
图形化的程序语言,又称为“G”语言。使用这种语言编程时,基本上不写程序代码,
取而代之的是流程图或流程图。它尽可能利用了技术人员、科学家、工程师所熟悉的术语、
图标和概念,因此,LabVIEW 是一个面向最终用户的工具。它可以增强你构建自己的科学和工程系统的能力,提供了实现仪器编程和数据采集系统的便捷途径。 使用它进行原理研究、
设计、测试并实现仪器系统时,可以大大提高工作效率。
利用 LabVIEW,可产生独立运行的可执行文件,它是一个真正的32位编译器。像许多重要的软件一样,LabVIEW 提供了 Windows,UNIX,Linux,Macintosh 的多种版本。
1,3 LabVIEW 的运行机制
1,3.1 LabVIEW 应用程序的构成
所有的 LabVIEW 应用程序,即虚拟仪器( VI),它包括前面板( front panel),流程图
( block diagram)以及图标 /连结器 (icon/connector)三部分。
前面板
前面板是图形用户界面,也就是 VI 的虚拟仪器面板,这一界面上有用户输入和显示输出两类对象,具体表现有开关、旋钮、图形以及其他控制( control)和显示对象( indicator) 。
图 1 所示是一个随机信号发生和显示的简单 VI 是它的前面板,上面有一个显示对象,以曲线的方式显示了所产生的一系列随机数。 还有一个控制对象——开关,可以启动和停止工作。
显然,并非简单地画两个控件就可以运行,在前面板后还有一个与之配套的流程图。
流程图
流程图提供 VI 的图形化源程序。在流程图中对 VI 编程,以控制和操纵定义在前面板上的输入和输出功能。流程图中包括前面板上的控件的连线端子,还有一些前面板上没有,
但编程必须有的东西,例如函数、结构和连线等。图1-2是与图1-1对应的流程图。我们可以看到流程图中包括了前面板上的开关和随机数显示器的连线端子,还有一个随机数发生器的函数及程序的循环结构。随机数发生器通过连线将产生的随机信号送到显示控件,为了使它持续工作下去,设置了一个 While Loop 循环,由开关控制这一循环的结束。
控制对象
(输 入 )
显示对象
(输出 )
图1-1 随机信号发生器的前
如果将 VI 与标准仪器相比较,那么前面板上的东西就是仪器面板上的东西,而流程图上的东西相当于仪器箱内的东西。在许多情况下,使用 VI 可以仿真标准仪器,不仅在屏幕上出现一个惟妙惟肖的标准仪器面板,而且其功能也与标准仪器相差无几。
图标 /连接器
VI 具有层次化和结构化的特征。一个 VI 可以作为子程序,这里称为子 VI( subVI),
被其他 VI 调用。图标与连接器在这里相当于图形化的参数,详细情况稍后介绍。
1.2.2 LabVIEW 的操作模板
在 LabVIEW 的用户界面上,应特别注意它提供的操作模板,包括工具( Tools)模板、
控制( Controls)模板和函数( Functions)模板。这些模板集中反映了该软件的功能与特征。
下面我们来大致浏览一下。
工具模板( Tools Palette)
该模板提供了各种用于创建、修改和调试 VI 程序的工具。如果该模板没有出现,则可以在 Windows 菜单下选择 Show Tools Palette 命令以显示该模板。当从模板内选择了任一种工具后,鼠标箭头就会变成该工具相应的形状。当从 Windows 菜单下选择了 Show Help Window 功能后,把工具模板内选定的任一种工具光标放在流程图程序的子程序( Sub VI)或图标上,就会显示相应的帮助信息。
下述工具中注意1和2的区别,2用于编程时,1用于运行程序时。
4是一个特有的工具,它并不是一个简单的画线工具,而是一个符合 LabVIEW 语言规定的对象连接工具。
工具图标有如下几种,
函数:随机数发生器
结构:循环
与前面板控件对应的连线端子
与前面板控件对应的连线端子
图1-2 随机信号发生器的流
下面的两个模板是多层的,其中每一个子模板下还包括多个对象。
控制模板( Control Palette)
注意:只有打开前面板时才能调用该模板
该模板用来给前面板设置各种所需的输出显示对象和输入控制对象。每个图标代表一类子模板。如果控制模板不显示,可以用 Windows 菜单的 Show Controls Palette 功能打开它,也可以在前面板的空白处,点击鼠标右键,以弹出控制模板。
控制模板如左图所示,它包括如下所示的一些子模板。子模板中包括的对象,我们在功能中用文字简要介绍。
图标 名称 功 能
1
Operate Value
(操作值)
用于操作前面板的控制和显示。使用它向数字或字符串控制中键入值时,工具会变成标签工具
2
Position/Size/Sele
ct (选择)
用于选择、移动或改变对象的大小。当它用于改变对象的连框大小时,会变成相应形状。
3
Edit Text(编辑文本)
用于输入标签文本或者创建自由标签。当创建自由标签时它会变成相应形状。
4
Connect Wire(连线)
用于在流程图程序上连接对象。如果联机帮助的窗口被打开时,把该工具放在任一条连线上,就会显示相应的数据类型。
5
Object Shortcut
Menu(对象菜单)
用鼠标左键可以弹出对象的弹出式菜单。
6
Scroll Windows
(窗口漫游)
使用该工具就可以不需要使用滚动条而在窗口中漫游。
7
Set/Clear
Breakpoint(断点设置/清除)
使用该工具在 VI 的流程图对象上设置断点。
8
Probe Data(数据探针)
可在框图程序内的数据流线上设置探针。通过控针窗口来观察该数据流线上的数据变化状况。
9
Get Color(颜色提取)
使用该工具来提取颜色用于编辑其他的对象。
10
Set Color(颜色设置)
用来给对象定义颜色。它也显示出对象的前景色和背景色。
功能模板 (Functions Palette)
注:只有打开了流程图程序窗口,才能出现功能模板。
功能模板是创建流程图程序的工具。该模板上的每一个顶层图标都表示一个子模板。
若功能模板不出现,则可以用 Windows 菜单下的 Show Functions Palette 功能打开它,也可以在流程图程序窗口的空白处点击鼠标右键以弹出功能模板。
功能模板如右图所示,其子模块如下所示。 (个别不常用的子模块未包含)
图标 子模板名称 功 能
1
Numeric(数值量) 数值的控制和显示。包含数字式、指针式显示表盘及各种输入框。
2
Boolean(布尔量) 逻辑数值的控制和显示。包含各种布尔开关、按钮以及指示灯等。
3
String & Path(字符串和路径)
字符串和路径的控制和显示。
4
Array & Cluster
(数组和簇)
数组和簇的控制和显示。
5
List & Table(列表和表格)
列表和表格的控制和显示
6
Graph(图形显示)
显示数据结果的趋势图和曲线图。
7
Ring & Enum(环与枚举)
环与枚举的控制和显示。
8
I/O(输入 /输出功能)
输入 /输出功能。于操作 OLE,ActiveX 等功能。
9
Refnum 参考数
10
Digilog
Controls(数字控制)
数字控制
11
Clussic
Controls(经典控制)
经典控制,指以前版本软件的面板图标。
12
Activex 用于 ActiveX 等功能。
13
Decorations(装饰)
用于给前面板进行装饰的各种图形对象。
14
Select a
Controls(控制选择)
调用存储在文件中的控制和显示的接口。
15
User Controls
(用户控制)
用户自定义的控制和显示。
图标 子模板名称 功 能
1
Structure(结构) 包括程序控制结构命令,例如循环控制等,以及全局变量和局部变量。
2
Numeric(数值运算)
包括各种常用的数值运算,还包括数制转换、三角函数、对数、复数等运算,以及各种数值常数。
3
Boolean(布尔运算)
包括各种逻辑运算符以及布尔常数。
4
String(字符串运算)
包含各种字符串操作函数、数值与字符串之间的转换函数,以及字符 (串 )常数等。
5
Array(数组)
包括数组运算函数,数组转换函数,以及常数数组等。
6
Cluster(簇)
包括簇的处理函数,以及群常数等。这里的群相当于
C 语言中的结构。
7
Comparison (比较)
包括各种比较运算函数,如大于、小于、等于。
8
Time & Dialog(时间和对话框)
包括对话框窗口、时间和出错处理函数等。
9
File I/O(文件输入 /输出)
包括处理文件输入 /输出的程序和函数。
10
Data
Acquisition(数据采集)
包括数据采集硬件的驱动,以及信号调理所需的各种功能模块。
11
Waveform(波形) 各种波形处理工具
12
Analyze(分析) 信号发生、时域及频域分析功能模块及数学工具 。
13
Instrument I/O
(仪器输入 /输出)
包括 GPIB(488,488.2)、串行,VXI 仪器控制的程序和函数,以及 VISA 的操作功能函数。
14
Motion & Vision
(运动与景像)
15
Mathematics(数学)
包括统计、曲线拟合、公式框节点等功能模块,以及数值微分、积分等数值计算工具模块。
16
Communication
(通讯)
包括 TCP,DDE,ActiveX 和 OLE 等功能的处理模块。
17
Application
Control(应用控制)
包括动态调用 VI、标准可执行程序的功能函数。
18
Graphics & Sound
(图形与声音)
包括 3D,OpenGL、声音播放等功能模块。包括调用动态连接库和 CIN 节点等功能的处理模块。
19
Tutorial(示教课程)
包括 LabVIEW 示教程序。
20
Report
Generation(文档生成)
21
Advanced(高级功能)
22
Select a VI(选择子 VI)
23
User Library(用户子 VI 库)
1.4 LabVIEW 的初步操作
1.4.1 创建 VI 和调用子 VI
我们通过例子来说明如何创建一个 VI。
练习1-1,
建立一个测量温度和容积的 VI,其中须调用一个仿真测量温度和容积的传感器子 VI。
步骤如下,
1.选择 File?New,打开一个新的前面板窗口。
2.从 Controls?Numeric 中选择 Tank 放到前面板中。
3.在标签文本框中输入“容积”,然后在前面板中的其他任何位置单击一下。
4.把容器显示对象的显示范围设置为 0.0 到 1000.0。
a,使用文本编辑工具( Text Edit Tool),双击容器坐标的 10.0 标度,使它高亮显示。
b,在坐标中输入 1000,再在前面板中的其他任何地方单击一下。 这时 0.0 到 1000.0 之间的增量将被自动显示。
5,在容器旁配数据显示。
将鼠标移到容器上,点右键,在出现的快速菜单中选 Visible
Iterms?Digital Display 即可。
6.从 Controls?Numeric 中选择一个温度计,将它放到前面板中。设置其标签为“温度”,显示范围为 0 到 100,同时配数字显示。可得到如下的前面板图。
图1-3 练习1-1的前面板图
7,Windows?Show Diagram 打开流程图窗口。从功能模板中选择对象,将它们放到流程图上组成下图(其中的标注是后加的)。
随机数发生器
乘法函数数值常数
进程监视器图1-4 练习1-1的流程图
该流程图中新增的对象有两个乘法器、两个数值常数、一个随机数发生器、一个进程监视器,温度和容积对象是由前棉板的设置自动带出来的。
a,乘法器和随机数发生器由 Functions?Numeric 中拖出,尽管数值常数也可以这样得到,但是建议使用 c 中的方法更好些。
b,进程监视器( Process Monitor)不是一个函数,而是以子 VI 的方式提供的,它存放在 LabVIEW\Activity 目录中,调用它的方法是在 Functions?Select a VI
下打开 Process Monitor,然后在流程图上点击一下,就可以出现它的图标。
注意,LabVIEW 目录一般在 Program Files\National Instruments\目录下。
8.用连线工具 将各对象按规定连接。 a 中的遗留问题创建数值常数对象的另一
种方法是在连线时一起完成。具体方法是:用连线工具在某个功能函数或 VI 的连线端子上单击鼠标右键,再从弹出的菜单中选择 Create Constant,就可以创建一个 具有正确的数据格式 的数值常数对象。
9,选择 File?Save,把该 VI 保存为 LabVIEW\ Activity 目录中的 Temp & Vol.vi。
在前面板中,单击 Run(运行) 按钮,运行该 VI。注意电压和温度的数值都显示在前面板中。
10.选择 File?Close,关闭该 VI 。
练习 1 -1 结束
附注与说明,
1.如果要查看某个功能函数或者 VI 的输入输出,需要从
Help菜单中选择 Show Help,再把光标置于这个功能函数或者 VI
上。例如进程监视器 VI 的 Help 窗口显示如下,
2.显示对象( Indicator),控制对象( Control)和数值常数对象
显示对象和控制对象都是前面板上的控件,前者有输入端子而无输出端子,后者正好相反,它们分别相当于普通编程语言中的输出参数和输入参数。数值常数对象可以看成是控制对象的一个特例。
在前面板中创建新的控制对象或显示对象时,
LabVIEW 都会在流程图中创建对应的端子。端子的符号反映该对象的数据类型。例如,DBL 符号表示对象数据类型是双精度数; TF 符号表示布尔数; I16
符号表示 16 位整型数; ABC 符号表示对象数据类型是字符串。
一个对象应当是显示对象还是控制对象必须弄清楚,否则无法正确连线。有时他们的图标是相似或相同的,可以根据需要明确规定它是显示对象还是控制对象。方法是将鼠标移到图标上,然后点右键,可出现快速菜单(例见右图)。如果菜单中的第一项是
Chang to Control,说明这是一个显示对象,你可以根据需要,将其变为控制对象。如果菜单中的第一项是 Chang to Indicator,
说明这是一个控制对象,你也可以根据需要,将其变为显示对象。
控制对象和显示对象都不能在流程图中删除,只能从前面板上删除。
3.关于连线
连线是程序设计中较为复杂的问题。流程图上的每一个对象都带有自己的连线端子,连线将构成对象之间的数据通道。因为这不是几何意义上的连线,因此并非任意两个端子间都可连线,连线类似于普通程序中的变量。数据单向流动,从源端口向一个或多个目的端口流动。不同的线型代表不同的数据类型。下面是一些常用数据类型所对应的线型和颜色,
类型 颜色 标量 一维数组 二维数组
整形数 兰色
浮点数 橙色
逻辑量 绿色
字符串 粉色
文件路径 青色
当需要连接两个端点时,在第一个端点上点击连线工具(从工具模板栏调用),然后移动到另一个端点,再点击第二个端点。端点的先后次序不影响数据流动的方向。
当把连线工具放在端点上时,该端点区域将会闪烁,表示连线将会接通该端点。当把连线工具从一个端口接到另一个端口时,不需要按住鼠标键。当需要连线转弯时,点击一次鼠标键,即可以正交垂直方向地弯曲连线,按空格键可以改变转角的方向。
接线头是为了帮助正确连接端口的连线。当把连线工具放到端口上,接线头就会弹出。
接线头还有一个黄色小标识框,显示该端口的名字。
线型为波折号的连线表示坏线。出现坏线的原因有很多,例如:连接了两个控制对象;
源端子和终点端子的数据类型不匹配(例如一个是数字型,而另一个是布尔型) 。可以通过使用定位工具点击坏线再按下 <Delete> 来删除它。选择 Edit?Remove Bad Wires 或者按下 <Ctrl-B> 可以一次删除流程图中的所有坏线。当 VI 无法运行,或者显示 Signal has
Loose Ends (信号丢失终端)的错误信息时,这是一个快捷的调试方法。
1.4.2 程序调试技术
1.找出语法错误
如果一个 VI程序存在语法错误,则在面板工具条上的运行按钮会变成一个折断的箭头,
表示程序不能被执行。 这时该按钮被称作错误列表。 点击它,则 LabVIEW 弹出错误清单窗口,
点击其中任何一个所列出的错误,选用 Find 功能,则出错的对象或端口就会变成高亮。
2.设置执行程序高亮
在 LabVIEW 的工具条上有一个画着灯泡的按钮,这个按钮叫做“高亮执行”按钮上。
点击这个按钮使它变成高亮形式,再点击运行按钮,VI 程序就以较慢的速度运行,没有被执行的代码灰色显示,执行后的代码高亮显示,并显示数据流线上的数据值。这样,你就可以根据数据的流动状态跟踪程序的执行。
3.断点与单步执行
为了查找程序中的逻辑错误,有时希望流程图程序一个节点一个节点地执行。使用断点工具可以在程序的某一地点中止程序执行,用探针或者单步方式查看数据。使用断点工具时,点击你希望设置或者清除断点的地方。断点的显示对于节点或者图框表示为红框,对于连线表示为红点。当 VI 程序运行到断点被设置处,程序被暂停在将要执行的节点,以闪烁表示。按下单步执行按钮,闪烁的节点被执行,下一个将要执行的节点变为闪烁,指示它将被执行。你也可以点击暂停按钮,这样程序将连续执行直到下一个断点。
4.探针
可用探针工具来查看当流程图程序流经某一根连接线时的数据值。从 Tools 工具模板选择探针工具,再用鼠标左建点击你希望放置探针的连接线。这时显示器上会出现一个探针显示窗口。该窗口总是被显示在前面板窗口或流程图窗口的上面。在流程图中使用选择工具或连线工具,在连线上点击鼠标右键,在连线的弹出式菜单中选择“探针”命令,同样可以为该连线加上一个探针。
1.4.3 子 VI 的建立
子 VI( SubVI)相当于普通编程语言中的子程序,也就是被其他的 VI 调用的 VI。可以将任何一个定义了图标和联接器的 VI 作为另一个 VI 的子程序。在流程图中打开
Functions?Select a VI….,就可以选择要调用的子 VI 。构造一个子 VI 主要的工作就是定义它的 图标和联接器 。
每个 VI 在前面板和流程图窗口的右上角都显示了一个默认的图标。启动图标编辑器的方法是,用鼠标右键单击面板窗口的右上角的默认图标,在弹出菜单中选择 Edit Icon。
下图显示了图标编辑器的窗口。 可以用窗口左边的各种工具设计像素编辑区中的图标形状。编辑区右侧的一个方框中显示了一个实际大小的图标。图标编辑器的具体使用细节参阅有关资料。
图1-5 图标编辑器窗口
联接器是 VI 数据的输入输出接口。如果用面板控制对象或者显示对象从子 VI 中输出或者输入数据,那么这些对象都需要在联接器面板中有一个连线端子。您可以通过选择
VI 的端子数并为每个端子指定对应的前面板对象以定义联接器。
定义联接器的方法是,用鼠标右键单击面板窗口中的图标窗口,在快捷菜单中选择
Show Connector。
联接器图标会取代面板窗口右上角的图标。 LabVIEW 自动选择的端子连接模式是控制对象的端子位于联接器窗口的左边,显示对象的端子位于联接器窗口右边。选择的端子数取决于前面板中控制对象和显示对象的个数。
联接器中的各个矩形表示各个端子所在的区域,可以用它们从 VI 中输入或者输出数据。如果必要,也可以选择另外一种端子连接模式。方法是在图标上单击鼠标右键单出快捷菜单,选择 Show Connector,再次弹出快捷菜单,选择 Patterns。下面我们通过一个练习说明具体操作。
练习 1 -2 为 VI 创建图标和联接器
1.打开 LabVIEW\Activity 目录中的 Temp & Vol.vi,这是练习1-1做的程序。
2.在前面板中,用鼠标右键单击窗口右上角的图标,在快捷菜单中选择 Edit Icon….,
也可以双击图标激活图标编辑器。注意只能在前面板中编辑图标和联接器。
3.删除默认图标。使用 Select Tool(矩形框),单击并拖动想要删除的部分,按下
<Delete>。也可以通过双击工具框中的阴影矩形删除图标。
4.用 Pencil Tool (铅笔工具)绘制一个温度计。
5.用 Text Tool(文本工具)创建文本。得到图标将如下图所示。
图1-6 编辑后的图标编辑器窗口
6.单击 OK,关闭编辑器。新创建的图标就显示在屏幕右上角的图标窗口中。
7.用鼠标右键单击前面板中的图标窗口,在快捷菜单中选择 Show
Connector,设置联接器端子连接模式。在默认情况下,LabVIEW 会根据前面板中的控制对象和显示对象的数目确定联接器的端子连接模式。因为前面板中有两个对象,所以联接器有两个端子,如左图所示。用鼠标右键单击联接器窗口,在快捷菜单中选择 Rotate 90
Degrees(旋转 90 度),注意联接器窗口的变化,如左图所示。
9.将端子连接到温度计和电压计,
a,点击联接器上部端子。光标自动变成连线工具,同时端子变成黑色。
b,单击温度显示对象。一个移动的虚线框把它包围起来,选中的端子的颜色变为与控制 /显示对象的数据类型一致的颜色。
如果单击前面板中的任何空白区域以后,虚线消失,选中的端子变暗,这表示您已经成功地把显示对象和上部端子连接起来。如果端子是白色,则表示没有连接成功。
c,重复步骤 a 和 b,把底部的端子和容积计连接起来。
d,用鼠标右键单击联接器,在快捷菜单中选择 Show Icon…,
10.选择 File?Save,保存该 VI。
这样这个 VI 就完成了,并也可以作为子 VI 被其他的 VI
调用。子 VI 的图标在主 VI 的流程图中代表它。 VI 的联接器
(含有两个端子)输出温度和电压。
练习 1 -2 结束
1.5 图表( chart)入门
图表( chart)是一种周期性更新数据的数字式图形显示对象。可以在
Controls?Graph 模板中找到两种图表:波形图和强度图
(后者不常用)。也可以自定义图表的格式,以满足自己的显示需要或者让它显示更多的数据。图表具有的特性有:
滚动条、图例、模板、数值显示、时间坐标显示。
右图显示了快速菜单中
Advanced?Update Mode 子菜单中提供的三种图表显示类型—— Strip chart(条状图),
Scope chart(示波器图)和 Sweep chart(扫描图)。默认模式是条状图。
练习 1-3 使用三种图表模式
目的:查看 VI 分别在三种模式下执行时图表的显示。
1.建立前面板及流程图如下
该程序中利用一个循环产生连续的 sin(i)函数值,并及时地在 chart 图表上显示出来,现在前面板上的 chart 是一个 strip,这是一个坐标式显示器,与纸带式图表记录器相似。每接受一个新数据,新数据就将显示在右侧,而原有数据移动到左侧
10
sin(x)
stop
100
图1-7 图表的例子
2.用鼠标选中 chart,点击右键,可在快速菜单中选择 Advanced?Update Mode 子菜单。
可以选择更换其他两种更新模式。
示波器模式是一个返回式的显示器,与示波器类似。每接受一个新数据时,它就把新数据绘制在原有数据的右侧。当数据曲线到达显示区的右边缘时,VI 会删除全部图形,从左边缘重新开始绘制曲线。示波器模式显然要快于条状图模式,因为它不会因为滚动产生溢出。
扫描模式更接近于示波器模式,但是当数据曲线到达显示区的右边时,不会变成空白,而是会出现一个移动的垂线,标记新数据的开始,并当 VI 添加新数据时穿过整个显示区。
练习 1-3 结束。
重叠式和堆栈式图区
LabVIEW 可以用同一个垂直坐标在一个图表中显示多个图区,这种图区被称为重叠式图区,也可使用多个垂直坐标,这时这种图形被称为堆栈式图区。请参考 Examples\ General\
Graphs\ charts.llb 中的 charts.vi 示例。
补充练习,
通过下面的要求练习 LabVIEW 的操作。
画出如右下所示的流程图,配以适当的前面板。注意连线时快捷菜单和 Create 功能的使用,和在前面板上替换不同的 Indicator 的方法。
3.14
cos(x)
sin(x)
图1-8 补充练习的面板及框图
第二章 程序结构
2.1 循环结构
2.1.1 While 循环
While 循环可以反复执行 循 环体的程序,直至到达某个边界条件。它类似于普通编程语言中的 Do 循环和 Repeat-Until 循环。 While 循环的框图是一个大小可变的方框,用于执行框中的程序,直到条件端子接收到的布尔值为 FALSE。
null 该循环有如下特点,
null 计数从 0 开始( i=0)。
null 先执行循环体,而后 i+1,如果循环只执行一次,那么循环输出值 i=0。
null 循环至少要运行一次。
循环变量条件端子
图2-1 While 循环示意图
练习 2-1 使用 While 循环和图表
目的:用 While 循环和图表获得数据,并实时显示。
创建一个可以产生并在图表中显示随机数的 VI。 前面板有一个控制旋钮可在 0 到 10 秒之间调节循环时间,还有一个开关可以中止 VI 的运行。学习怎样改变开关的动作属性,以便不用每次运行 VI 时都要打开开关。操作步骤如下,
前面板
控制开关
1.0
0.0
0.2
0.4
0.6
0.8
10230
随机信号
10.0
0.0
2.0
4.0 6.0
8.0
循环延时
ON
OFF
图2-2 练习2-1的前面板
1,选择 File?New,打开一个新的前面板。
2,选择 Controls?Boolean,在前面板中放置一个开关。
设置开关的标签为控制开关。
3,使用标签工具创建 ON 和 OFF 的标签,放置于开关旁。
4,选中 Controls?Graph,在前面板中放置一个波形图 (是
chart,而不是 graph)。设置它的标签为随机信号。这个图表用于实时显示随机数。
5,把图表的纵坐标改为 0.0 到 1.0。方法是用标签工具把最大值从 10.0 改为 1.0。
6,选择 Controls?Numeric,在前面板中放置一个旋钮。
设置旋钮的标签为循环延时。这个旋钮用于控制 While 循环的循环时间。
流程图
7,开流程图,按照下图创建流程图。
随机信号循环延时控制开关
图2-2 练习2-1的流程图
a,从 Functions?Structures 中选择 While 循环,把它放置在流程图中。 将其拖至适当大小,将相关对象移到循环圈内。
b,从 Functions? Numeric 中选择随机数( 0-1)功能函数放到循环内。
c,在循环中设置 Wait Until Next ms Multiple 函数
( Functions?Time & Dialog),该函数的时间单位是毫秒,按目前面板旋钮的标度,可将每次执行时间延迟 0 到 10 毫秒。
d,照上面所示的流程图连线,把随机数功能函数和随机信号图表输入端子连接起来,并把启动开关和 While 循环的条件端子连接。
8,返回前面板,调用操作工具后单击垂直开关将它打开。
9,把该 VI 保存为 LabVIEW\ Activity 目录中的 Random
Signal.vi。
10,执行该 VI。 While 循环的执行次数是不确定的,只要设置的条件为真,循环程序就会持续运行。在这个例子中,只要开关打开( TRUE),框图程序就会一直产生随机数,并将其在图表中显示。
11,单击垂直开关,中止该 VI。关闭开关这个动作会给循环条件端子发送一个 FALSE 值,从而中止循环。
12,用鼠标右键单击图表,选择 Data Operations?Clear
Chart,清除显示缓存,重新设置图表。
练习 2-1结束
附注与说明
布尔开关的机械动作,
布尔开关有 6 种机械动作属性可供选择。在前面板上用鼠标右键单击开关,在快捷菜单中选择 Mechanical Action 就可以看到这些可选的动作。 LabVIEW 还提供了一个范例示范这些动作,它是位于 Examples\ General\ Controls\ booleans.llb 的 Mechanical Action of
Booleans.vi。
2.1.2 移位寄存器( Shift Register)
移位寄存器可以将数据从一个循环周期传递到另外一个周期。在程序设计中,经常要用到它.创建一个移位寄存器的方法是,用鼠标右键单击循环的左 边或者右 边,在快捷菜单中选择 Add Shift Register。如右图所示。
移位寄存器在流程图上用在循环边框上相应的一对端子来表示。右边的端子中存储了一个周期完成后的数据,这些数据在这个周期完成之后将被转移到左边的端子,赋给下一个周期。移位寄存器可以转移各种类型的数据--数值、布尔数、数组、字符串等等。它会自动适应与它连接的第一个对象的数据类型。下图表示了它的工作过程,
图2-3 Shift Register 的工作过程
可以令移位寄存器记忆前面的多个周期的数值。 这个功能对于计算数据均值非常有用。 还可以创建其他的端子访问先前的周期的数据,方法是用鼠标右键单击左边或者右边的端子,在快捷菜单中选择 Add Element。例如,如果某个移位寄存器左边的端口含有三个元素,那么就可以访问前三个周期的数据。
练习 2-2 使用移位寄存器
目的:创建一个可以在图表中显示运行平均数的 VI。
前面板
1.打开一个新的前面板,按照下图所示创建对象。
2.把波形图表的坐标范围改为 0.0 到 2.0。
3.在添加竖直坐标之后,用鼠标右键单击它,在快捷菜单中选择 Mechanical
Action?Latch When Pressed,再 选 择 Operate?Make Current Values Default,把 ON 状态设置为默认状态。
2.0
0.0
0.5
1.0
1.5
500
随机数
Boolean
ON
OFF
缺省值,ON
机械动作
Latch When
Pressed
图2-4 练习2-2的前面板
流程图
4.按下图创建流程图。
0.5
随机数
4.00
500
Boolean
图2-4 练习2-2的流程图
5.在流程图中添加 While 循环 (Functions?Structures),创建移位寄存器。
a,用鼠标右键单击 While 循环的左边或者右边,在快捷菜单中选择 Add Shift Register。
b,用鼠标右键单击寄存器的左端子,在快捷菜单中选择 Add Element,添加一个寄存器。用同样的方法创建第三个元素。
6,Random Number (0–1)函数( Functions?Numeric)——产生 0 到 1 之间的某个随机数。
7,Compound Arithmetic 函数( Functions?Numeric)——在本练习中,它将返回两个周期产生的随机数的和。如果要加入其他的输入,只需用右键单击某个输入,从快捷菜单中选择 Add Input。
8.除法函数( Functions?Numeric)——在本练习中,它用于返回最近四个随机数的平均值。
9.数值常数( Functions?Numeric)——在 While 循环的每个周期,Random Number (0–1)
函数将产生一个随机数。 VI 就将把这个数加入到存储在寄存器中的最近三个数值中。
Random Number (0–1)再将结果除以 4,就能得到这些数的平均值(当前数加上以前的三个数) 。然后再将这个平均值显示在波形图中。
10,Wait Until Next ms Multiple 函数 ( Functions?Time & Dialog)——它将确保循环的每个周期不会比毫秒输入快。在本练习中,毫秒输入的值是 500 毫秒。如果用鼠标右键单击图标,从快捷菜单中选择 Visible?Label,就可以看到 Wait Until Next ms Multiple
的标签。
11,用鼠标右键单击 Wait Until Next ms Multiple 功能函数的输入端子,在快捷菜单中选择 Create Constant。出现一个数值常数,并自动与功能函数连接。
12,将 Constant 设置为 500。这样连接到函数的数值常数设置了 500 毫秒的等待时间。
因此循环每半秒执行一次。注意,VI 用一个随机数作为移位寄存器的初始值。如果没有设置移位寄存器端子的初始值,它就含有一个默认的数值,或者上次运行结束时的数值,因此开始得到的平均数没有任何意义。
13,执行该 VI,观察过程。
14,把该 VI 保存为 LabVIEW\Activity 目录下的 Random Average.vi。
练习 2-2 结束。
附注:移位寄存器的初值,
上面的练习中对移位寄存器设置了初值 0.5。如果不 设这个初值,默认的初值是0。
在这个例子中,一开始的计算结果是不对的,只有到循环完3次后移位寄存器中的过去值才填满,即第4次循环执行后可以得到正确的结果。
2.1.3 For 循环
For循环用于将某段程序执行指定次数。 和 While 循环一样,
它不会立刻出现在流程图中,而是出现一个小的图标,而后您可以修改它的大小和位置。具体的方法是,先单击所有端子的左上方,然后按下鼠标,拖曳出一个包含所有端子的矩形。释放鼠标时就创建了一个指定大小和位置的 For 循环。
100
图表
For 循环将把它的框图中的程序执行指定的次数,For 循环具有下面这两个端子,
N,计数端子(输入端子)——用于指定循环执行的次数。
I,周期端子(输出端子)——含有循环已经执行的次数。
上图显示了一可以产生 100 个随机数并将数据显示在一个图表上的 For 循环。在该例中,i 的初值是 0,终值是 99。
练习 2-3 使用 For 循环
目的:用 For 循环和移位寄存器计算一组随机数的最大值。
1,打开一个新的前面板,按照下图创建对象。
a,将一个数字显示对象放在前面板,设置它的标签为,最大值”。
b,将一个波形图表放在前面板,设置它的标签为“随机数”。将图表的纵坐标范围改为 0.0 到 1.0。
c,在图表的快捷菜单中选择 Visible Items?Scrollbar
和 Digital Display,并隐藏 Plot Legend。
d,用移位工具修改滚动栏的大小。
100
0
随机数最大值图2- 5 练习2- 3 的面板和流程图
2,按照上图画流程图。
3.在流程图中放置一个 For 循环
( Functions?Structures)。
4.在 For 循环的边框处单击鼠标右键,在快捷菜单中选择
Add Shift Register。
5.将下列对象添加到流程图。
a Random Number (0– 1)函数( Functions?Numeric)—
—产生 0 到 1 之间的某个随机数。
b 数值常数( Functions?Numeric)——在这个练习中需要将移位寄存器的初始值设成 0。
c Max&Min 函数( Functions?Comparison)——输入两个数值,再将它们的最大值输出到右上角,最小值输出到右下角。
这里只需要最大值,只用连接最大值输出。
d 数值常数( Functions?Numeric)—— For 循环需要知道需要执行的次数。本练习中是 100 次。
6.按照上图连接各个端子。
7.运行该 VI。
8.将该 VI 保存为 LabVIEW\ Activity 目录下的 Calculate
Max.vi。
练习 2-3 结束。
2.2 分支结构,Case
Case 结构含有两个或者更多的子程序( Case),执行那一个取决于与选择端子或者选择对象的外部接口相连接的某个整数、
布尔数、字符串或者标识的值。必须选择一个默认的 Case 以处理超出范围的数值,或者直接列出所有可能的输入数值。 Case
结构见下图,各个子程序占有各自的流程框,在其上沿中央有相应的子程序标识,Ture,False 或1、2、3…。按钮用来改变当前显示的子程序(各子程序是重叠放在屏幕同一位置上的)。
False
练习 2 -4 使用 Case 结构
子程序标识按钮条件端子
目的:创建一个 VI以检查一个数值是否为正数。如果它是正的,VI就计算它的平方根,反之则显示出错。
前面板
1,打开一个新的前面板,并按照下图所示创建对象。控制对象用于输入数值,显示对象用于显示该数值的平方根。
流程图
2,照下图创建流程图。
2.00
Number
1.41
SQRT
SQRT
Number
True
SQRT
Number
-999.00
Errot...
False
图2-6 练习2-4的面板和流程图
3,从 Functions?Structures 中选择一个 Case 结构,并放置在在流程图中。 Case 结构是一个可以改变大小的方框。先来做 Ture 的情况,照流程图上半部分构造。
a Greater Or Equal To 0? 函数 ( Functions?Comparison)
——如果输入数值大于或者等于 0 就会返回一个 TRUE 值。
b Square Root 函数( Functions?Numeric)——返回输入数值的平方根。
c 连好线
d 点击 Case 框的选择按钮,转入 False 情况编程
e 数值常数( Functions?Numeric)——这里用于显示错误的代数值 -999.00。
f One Button Dialog 函数( Functions?Time &
Dialog)——在这里它用于显示一个对话框,内容是
Error...。
g 字符串常数 (Functions?String)——用 Edit Text
A
D
C
B
Tools 在对话框中输入字符串。
h 该 VI 在 TRUE 或者 FALSE 情况下都会执行。如果输入的数值大于等于 0,VI 会执行 TRUE Case,返回该数的平方根,
否则将会输出- 999.00,并显示一个对话框,内容为 Error...。
4,返回前面板,运行该 VI。修改标签为 Number 的数字式控制对象的数值,分别尝试一个正数和负数。注意,当把数字式控制对象的值改为负数时,LabVIEW 会显示 Case 结构的 FALSE
Case 中设置的出错信息。
5,保存该 VI 到 LabVIEW\ Activity 目录中的 Square
Root.vi。
VI 的算法
本练习中的流程图功能相当于代码式编程语言中的下列伪代码,
if (Number >= 0) then
Square Root Value = SQRT(Number)
else
Square Root Value = -999.00
Display Message "Error.,"
end if
练习 2 -4 结束。
2.3 顺序结构和公式节点
2.3.1 顺序结构( Sequence Structure)
在代码式的传统编程语言中,默认的情况是,程序语句按照排列顺序执行,但 LabVIEW
中不同,它是一种图形化的数据流式编程语言。在图2-7左图中,假设有 A,B,C,D4
个节点,其数据流向如右图所示。按照数据流式语言的约定,任何一个节点只有在所有
图2-7 顺序结构的说明
的输入数据有效时才会执行,所以图中,当且仅当 A,B,C3个节点执行完,使得 D 节点的
3个输入数据都到达 D 节点后,D 节点才执行。但是你要注意,这里并没有规定 A,B,C3
个节点的执行顺序。在 LabVIEW 中这种情况下,A,B,C 的执行顺序是不确定的,如果你需要对它们规定一个确定的顺序,那就需要使用本节介绍的“顺序结构” 。
图2-7中的右边是顺序结构的图标,它看上去像是电影胶片。它可以按一定顺序执行多个子程序。首先执行 0 帧中的程序,然后执行 1 帧中的程序,逐个执行下去。与 Case 结构类似,这多帧程序在流程图中占有同一个位置。
练习 2 -5 使用顺序结构
目的:创建一个 VI,计算生成等于某个给定值的随机数所需要的时间。
前面板
1,打开一个新的前面板,并按照下图所示创建对象。
50
给定数据
50
当前值
6
执行次数
0.00
匹配时间(秒)
图2-8 练习2-5的前面板
我们约定数据是0到 100 范围的整数。 当前值用于显示当前产生的随机数。,执行次数”
用于显示达到指定值循环执行的次数。匹配时间用来显示达到指定值所用的时间。
流程图
读取初始时间
0 [0..2]
100.00
给定数据当前值执行次数匹配计算
1 [0..2]
1000.00
匹配时间(秒)
计算延时时间(秒)
2 [0..2]
图2-8 练习2-5的流程图(共3帧)
1,在流程图中放置顺序结构 (Functions?Structures)。
2,用鼠标右键单击帧的边框,在快捷菜单中选择 Add
Frame After,创建一个新帧。重复这个步骤,再创建一个帧。
共3桢。
3,选中第0桢,设置读取初始时间(子)程序
4,第 0 帧的下边框上含有一个小方框,其中有一个箭头。
这个方框叫做顺序局部变量,可以在同一个顺序结构中的各个帧之间传递数据。用鼠标右键单击第 0 帧的底部边框,选择 Add
Sequence Local,创建顺序局部变量。顺序局部变量显示为一个空的方块。当您将某个功能函数与顺序局部变量相连时,方块中的箭头就会自动显示。
5,Tick Count (ms) 函数( Functions?Time &
Dialog)——返回启动到现在的时间(以毫秒为单位)。
在这里例子里需要使用两个这个函数。另一个在第2帧中。
6,按图连好线。转入第1帧。该帧是匹配计算,内含一个循环结构。该图中使用的新函数有,
Round to Nearest 函数( Functions?Numeric)——在该例中,它用于取 0 到 100 之间的随机数到距离最近的整数。
Not Equal?函数( Functions? Comparison)——在该例中,它将随机数和前面板中设置的数相比较,如果两者不相等会返回 TRUE 值,否则返回 FALSE。
Increment 函数( Functions?Numeric)——在该例中,
它将 While 循环的计数器加 1。
7,按图连好线。转入第2帧
在第 0 帧中,Tick Count ( ms)功能函数将以毫秒为单位表示当前时间。这个数值被连到顺序局部变量,这样它就可以被后续的帧使用。在第 1 帧中,只要函数返回的值与指定值不等,
VI 就会持续执行 While 循环。在第 2 帧中,Tick Count ( ms)
功能函数以毫秒为单位返回新的时间。 VI 从中减去原来的时间
(由第 0 帧通过顺序局部变量提供)就可以计算出花费的时间。
8,返回前面板,在 Number to Match 控制对象中输入一个数值,执行该 VI。
9,把该 VI 保存为 LabVIEW\ Activity 目录下 Time to
Match.vi。
练习 2-5 结束。
附注与说明,设置数据范围
在设定一个数据对象时,可以设置对输入数据的限制,利用快捷键选择 Data Range… 选项,将会出现如下对话框,
图2-9 设置数据范围
它可以防止用户创建的控制对象或显示对象的值超出某个预设的范围。 您可以选择忽略这个值,将它强制修改到范围以内,
或暂停程序的执行。在程序执行时,如果发生溢出错误,溢出错误符号将显示在工具栏中的执行按钮的位置。而且,一个立体的黑框将把发生溢出的控制对象包围起来。
2.3.2 公式节点( Formula Node)
公式节点是一个大小可变的方框,可以利用它直接在流程图中输入公式。从 Functions?Structures 中选择公式节点就可以把它放到流程图中。当某个等式有很多变量或者非常复杂时,这个功能就非常有用。例如等式,y = x
2
+ x + 1 使用公式节点可以表示为,
图2-10 公式节点示意图
利用公式节点可以直接输入一个或者多个复杂的公式,而不用创建流程图的很多子程序。使用文本编辑工具来输入公式。创建公式节点的输入和输出端子的方法是,用鼠标右键单击第 0
帧的底部边框,选择 Add Input (Add Output)。再在节点框中输入变量名称。变量名对大小写敏感。然后就可以在框中输入公式。每个公式语句都必须以分号( ;)结尾。
公式节点的帮助窗口中列出了可供公式节点使用的操作符、
函数和语法规定。一般说来,它与 C 语言非常相似,大体上一个用 C 写的独立的程序块都可能用到公式节点中。 但是仍然建议不要在一个公式节点中写过于复杂的代码程序。
下面这个例子显示了如何在一个公式节点中执行不同条件时的数据发送。
请阅读下面这段程序代码,如果 X 为正数,它将算出 X 的平方根并把该值赋给 Y,如果 X 为负数,程序就给 Y 赋值 -99。
if (x >= 0) then
y = sqrt(x)
else
y = -99
end if
可以用公式节点取代上面这段代码,如下图所示,
output
input Y=(X>=0)?sqrt(X):-99;
Y
X
注意:公式节点中变量字母 X,Y 大、小写是有区别的,开方的函数 sqrt(X)中函数名称是小写。
练习 2-6 使用公式节点
目的:创建一个 VI,它用公式节点计算下列等式,
y1 = x
3
– x
2
+ 5
y2 = m* x + b
x 的范围是从 0 到 10。 可以对这两个公式使用同一个公式节点,并在同一个图表中显示结果。
前面板
30.00
m
20.00
b
1000.0
0.0
200.0
400.0
600.0
800.0
100 1 2 3 4 5 6 7 8 9
y1
y2
Waveform Graph
图2-11 练习2-6的面板
1,打开一个新的前面板,按照上图(该图中包含运行结果) 创建前面板中的对象。 波形图显示对象用于显示等式的图形。
该 VI 使用两个数字式控制对象来输入 m 和 b 的值。
流程图
2,按照下图创建流程图。
图2-12 练习2-6的流程图
在创建某个输入或者输出端子时,必须给它指定一个变量名。这个变量名必须与公式节点中使用的变量名完全相符。
公式节点中,在边框上单击鼠标右键,在快捷菜单中选择
Add Input,可以创建三个输入端子。在快捷菜单中选择 Add
Output,创建输出端子。
x 的范围是从 0 到 10(包括 10),就必须连接 11 到计数端子。
Build Array ( Functions?Array)——在这个例子中,它用于将两个数据构成数组形式提供给一个多曲线的图形中。通过用变形工具拖拉边角就可以创建两个输入端子。
11
y1=x**3+x**2+5;
y2=m*x+b;
y2
x
b
y1
m
m
Formule Node
b
Waveform Graph
3,返回前面板,尝试给 m和 b赋以不同的值再执行该 VI。
4,把该 VI 保存为 LabVIEW/Activity 目录下的
Equations.vi。
练习 2-6 结束。
第三章 数据类型:数组、簇和波形
3.1 概述
数组是同类型元素的集合。一个数组可以是一维或者多维,
如果必要,每维最多可有 2
31
- 1 个元素。可以通过数组索引访问其中的每个元素。索引的范围是 0 到 n – 1,其中 n 是数组中元素的个数。图3-1所显示的是由数值构成的一维数组。注意第一个元素的索引号为 0,第二个是 1,依此类推。数组的元素可以是数据、字符串等,但所有元素的数据类型必须一致。
图3-1 数组示意图
簇( Cluster)是另一种数据类型,它的 元素可以是不同类型的数据。它类似于 C 语言中的 stuct。使用簇可以把分布在流程图中各个位置的数据元素组合起来,这样可以减少连线的拥挤程度。减少子 VI 的连接端子的数量。
波形( Waveform)可以理解为一种簇的变形,它不能算是一种有普遍意义的数据类型,
但非常实用。
3.2 数组的创建及自动索引
3.2.1 创建数组
一般说来,创建一个数组有两件事要做,首先要建一个数组的“壳” ( shell),然后在这个壳中置入数组元素(数或字符串等) 。
如果需要用一个数组作为程序的数据源,可以选择
Functions?Array?Array Constant,将它放置在流程图中。然后再在数组框中放置数值常量、布尔数还是字符串常量。下图显示了在数组框放入字符串常量数组的例子。左边是一个数组壳,中间的图上已经置入了字符串元素,右边的图反映了数组的第0个元素为:,ABC”,后两个元素均为空。
ABC
0
Array Constant
ABC
0
Array Constant
0
Array Constant
图3-1 数组的创建
在前面板中创建数组的方法是,从 Controls 模板中选择
Array & Cluster,把数组放置在前面板中,然后选择一个对象
(例如数值常量) 插入到数组框中。 这样就创建了一个数值数组。
也可以直接在前面板中创建数组和相应的控制对象,然后将它们复制或者拖曳到流程图中,创建对应的常数。
还有很多在流程图中创建和初始化数组的方法,有些功能函数也可以生成数组。
3.2.2 数组控制对象、常数对象和显示对象
通过把数组与数值、布尔数、字符串或者簇组合在一起,可以在前面板和流程图中创建任何一种控制对象、常数对象和显示对象。数组元素不能是数组、图表或者图形。如果您想查看一些数组的例子,请查看 Examples\ General\ arrays.llb 中的例子。
3.2.3 自动索引
For 循环和 While 循环可以自动地在数组的上下限范围内编索引和进行累计。这些功能称为自动索引。在启动自动索引功能以后,当把某个外部节点的任何一维元素连接到循环边框的某个输入通道时,该数组的各个元素就将按顺序一个一个地输入到循环中。循环会对一维数组中的标量元素,或者二维数组中的一维数组等编制索引。在输出通道也要执行同样的工作――数组元素按顺序进入一维数组,一维数组进入二维数组,依此类推。
在默认情况下,对于每个连接到 For 循环的数组都会执行自动索引功能。可以禁止这个功能的执行,方法是用鼠标右键单击通道(输入数组进入循环的位置),在快捷菜单中选择 Disable
Indexing。
练习 3-1 创建一个自动索引的数组
目的:使用 For 循环的自动索引功能创建数组,并用一个图形( Graph)显示该数组。
前面板
图3-2 练习3-1的面板
2,打开一个新的前面板。
3,选择 Controls?Array & Cluster,在前面板中放置一个数组。设置它的标签为 Waveform Array。
4,选择 Controls?Numeric,在数组框中插入一个数字式显示对象。如右图所示。它用于显示数组的内容。
5,选择 Controls?Graph,在前面板中放置一个波形图。
设置它的标签为 Waveform Graph。
6,隐藏图例和模板。
7,用鼠标右键单击图形,并在快捷菜单中取消选中 Y
Scale?Autoscale Y,禁止自动坐标功能。
8,使用文本工具,把 Y 轴的范围改为 -0.5 到 1.5。
流程图
9,按照下图创建流程图。
图3-2 练习3-1的流程图
null 由 Functions?Select a VI… 寻找
LabVIEW\ activity 目录下的 Generate Waveform
VI,它的作用是返回波形中的某一点。这个 VI
需要输入一个索引,我们将循环周期连接到这个输入。
null 注意 Generate Waveform VI 连出来的连线在循环边界变成一个数组时会变粗,正是在这个边界处形成了一维数组。
null For 循环会自动累计边界内的数组。 这种功能叫做自动索引。在这个例子中,连接到循环计数输入的数值常数令 For
循环创建了一个由 100 个元素组成的数组。
null Bundle 函数( Functions? Cluster)—
—将图块中的各个组件组合成一个簇,在正确连接以前需要改变该函数的图标的大小。将移位工具放在图标的左下角。变形工具会变成如左图所示,拖曳鼠标直到出现第三个输入端子。
null 数值常数( Functions?Numeric)——三个数值常数用于设置 For 循环执行的周期数 N=100,初始 X=0 和 delta X=1。
10,从前面板执行该 VI。 该 VI 将把自动索引后的波形图数组显示在波形图中。
11,把 X 的 delta 值改为 0.5,X 的初始值改为 20。再次执行该 VI。注意,波形图现在同样显示 100 个点,而每个点的初始值为 20,X 的 delta 值为 0.5(见 X 轴)。
12,只需在显示器中输入元素的索引号就可以查看波形数组中的任何元素。如果输入的数比数组的元素个数大,那么显示
X0Delta X
1 0
100
Waveform Graph
Waveform Array
器将变暗,表示您没有为该元素设置索引。
如果需要一次查看多个元素,可以通过改变数组显示对象的大小来实现。 把定位工具放置在数组框的右下角。工具将变成右图所示的变形工具。当工具变形时,用鼠标拖曳数组的右边或者下边。 数组现在就可以按照元素索引的上升顺序显示多个素,以某个与指定索引对应的元素开始,如下图所示。
图3-3 练习3-1中多个数组元素的同时观察
在前面的流程图中,您为波形图指定了初始的 X 值和 delta
X 值。默认的 X 初始值是 0,delta X 值是 1。这样,也可以把波形数组直接连接到波形图端子,而无需指定初始的 X 值和
delta X 值,如图3-4所示。
图3-4 练习3-1使用默认 X 及 Delta X 时简化后的流程图
13,按上图删除 Bundle 功能函数和它所连接的常数对象。
方法是用移位工具选择该功能函数和连接的常数对象,按下
<Delete>。再选择 Edit?Remove Bad Wires。按照上图完成流程图的连线。
14,执行该 VI。注意初始的 X 值是0,delta X 值是 1。
null 多图区图形
可以创建含有多条曲线的图形,方法是创建一个数组,用它来汇集传给单图区图形的类型的数据元素。
Build Array
0.5
100
50
Waveform Graph
Array
图3-5 练习3-1多图区图形的流程图
15,按照上图创建流程图。
null 正弦函数
( Functions?Numeric?Trigonometric)——在这里,它用于在 For 循环中创建一个由数据点组成的数组,表示一个正弦波周期。
null Pi 常数( Functions?Numeric?Additional
Numeric Constants)
null Build Array ( Functions?Array)——在这里,它用于创建合适的数据结构 (一个二维数组),
在波形图中绘制两条曲线。。用移位工具拖曳边角可以增大该函数的面积,创建两个输入端子。
16,返回前面板,执行该 VI。注意同一个波形中的两个图区。默认情况下,它们的 X 初始值都是 0,delta X 初始值都是
1。下图是该程序的运行结果(前面板未改动)。
17,把该 VI 保存为 LabVIEW\ Activity 目录中的 Graph
Waveform Arrays.vi。
18,可以修改图形中的某个图区的外观。方法是,用鼠标右键单击这个图形,再从弹出菜单选择对应的图例。
-0.09
0
Array
1.5
-0.5
0.0
0.5
1.0
1000 10 20 30 40 50 60 70 80 90
Plot 0
Waveform Graph
图3-6 练习3-1多图区图形的面板显示
练习 3-1 结束。
在上面这个例子中,由于计算端子连接了一个值为 100 的常数对象,所以 For 循环将执行 100 次。下面这个例子显示了另外一种控制循环执行次数的方法。
更详细的例子建议调阅 Examples,Fundamentals,Graphs
and Charts,Graph Examples,Waveform Graph 例子。
练习 3-2 对输入数组使用自动索引功能
目的:打开并执行一个 VI,它将在一个 For 循环中使用自动索引功能处理一个数组。
1,选择 File?Open…,打开
Examples\ General\ arrays.llb 中的 Separate Array Values
VI 。
2,打开流程图。下面的示意图显示的是在 TRUE 和 FALSE
时的情况。
0
0.0
Initialize
Array
Build Array
True
Negative Array
Positive Array
Input Array
0
0.0
Initialize
Array
Build Array
False
Negative Array
Positive Array
Input Array
图3-7 练习3-2的流程图
注意,Input Array 引出的连线与 For 循环外的粗线不同,
表示这是一个数组,而循环内部的细线则表示这是一个数组元素。 数组元素在每个循环期间将自动编号。
null 用自动索引功能设置 For 循环的计数器
注意,计数器端子还没有连线。当您对某个进入 For
循环的数组使用自动索引功能时,循环就将根据数组的大小执行相应的次数,这样就无需连接某个值到计数器的端口。如果对一个以上的数组使用自动索引功能,或者在使用自动索引功能之外还需要设置计数器时,实际的循环次数将是其中最小的数。
3,执行该 VI。在输入的八个数中,可以看到 4 个属于正数数组,另外 4 个属于负数数组。
4,从流程图中将一个值为 5 的常数对象连接到 For 循环的计数器端子。执行该 VI。可以看到尽管输入数组仍然有八个元素,但是 3 个位于正数数组,另外 2 个位于负数数组。 这说明,
如果设置了 N 并开启了自动索引功能,那么实际循环的次数将取较小的数。
5,关闭该 VI,不要保存任何修改。
注:练习 3-2的算法说明
下面是一段伪代码,解释上面的算法,假定输入数组为 A(已赋值),B(正数),C(负数)。 Sbr,Scr 分别是与 B 数组、
C 数组对应的右寄存器数组,Sbl,Scl 分别是与 B 数组,C 数组对应的左寄存器数组,size 运算为测数组实际大小,ins 运算为将一个数插入数组中最左边的空位。
B=0
初始化
C=0
K=size(A(.))
测 A数组大小
For i=0 to k-1
p=A(i)
取第 I个元素值
if p>=0 then
Ins p,Sbr
将 p值插入右寄存器
Else
Ins p,Scr
end if
Sbl=Sbr
右寄存器值送给左寄存器
Scl=Scr
Next i
B=Sbr
右寄存器值送到正数组
C=Scr
Print B
显示
Print C
End
练习 3-2 结束。
3.3 数组功能函数
LabVIEW 提供了很多用于操作数组的功能函数,位于
Functions?Array 中。 其中包括 Replace Array Element,,Search 1D
Array,Sort 1D Array,Reverse 1D Array 和 Multiply Array
Elements 等等。
null 创建数组—— Build Array 函数( Functions?Array),用于根据标量值或者其他的数组创建一个数组。
开始时,Build Array 函数具有一个标量输入端子。您可以根据需要向该功能函数中加入任意数量的输入,输入可以是标量或者数组。如果要添加其他的输入,用鼠标单击函数的左侧,在弹出菜单中选择 Add Element Input 或者 Add Array Input。还可以用变形工具来增大节点的面积(把移位工具放置在某个对象的边角就会变成变形光标) 。也可以使用变形光标或者选择 Remove Input 来删除输入。
下图显示了利用流程图中的常数对象的值创建和初始化数组的两种方法。左侧的方法是,将 5 个字符串常数放入一个一维字符串数组中。右侧的方法是,将三组数值常数放入三个一维数值数组,再将这三个数组组成一个二维数组。这样最后产生的是一个 3x3 的数组,
三列分别是 3,4,7; –1,6,2; 5,–2,8.。
还可以通过结合其他的含有标量元素的数组来创建数组。例如,假设有两个数组,三个标量元素,可把它们组成一个新的数组,顺序是:数组 1,标量 1,标量 2,数组 2,标量 3。
null 初始化数组( Initialize Array)——用于创建所有元素值都相等的数组。下图中,该功能函数创建了一个一维数组。
元素输入端子决定每个元素的数据类型和数值,维长度输入端子决定数组的长度,例如,
假设元素类型是长整型,值为 5,维长度为 100,那么创建的数组是一个一维的、由 100 个值为 5 的长整型元素组成的数组。也可以从前面板控制端子、流程图常数或者程序其他部分的计算结果得到输入。
创建和初始化一个多维数组的方法是,用鼠标右键单击函数的右下侧,在弹出菜单中选择 Add Dimension。还可以使用变形光标来增大初始化数组节点的面积,为每个增加的维添加一个维长度输入端子。也可以通过缩小节点的方法来删除维,即从函数的弹出菜单中选择
Remove Dimension,或者使用变形光标。下面的示意图显示了怎样初始化一个三维数组。
如果所有的维长度输入都是 0,该函数会创建一个具有指定数据类型和维数的空数组。
null 数组大小—— Array Size 函数,返回输入数组中的元素个数。
null 数组子集( Array Subset)——选取数组或者矩阵的某个部分。
该函数可以返回从某个指针开始的部分数组,并包括了长度元素。下图显示了一些数组子集的例子,注意,数组索引从 0 开始。
null 索引数组( Index Array)——用于访问数组中的某个元素。
下图显示了一个索引函数的例子,它用于访问数组中的第三个元素。注意,因为第一个元素的索引为 0,所以第三个元素的索引是 2。
将一个二维数组与 Index Array 函数相连,Index Array 就会含 2 个索引端子。将一个三维数组与 Index Array 函数相连,Index Array 就会含 3 个索引端子。余类推。可以使用的索引端的符号是一个黑方快,被禁止使用的索引端( Disable Indexing)是一个空心的小方框。
当给一个被禁止使用的索引端连接上一个 Constant 或 Control 是它会自动变为黑方快,即变为可以索引,相反原来一个可以使用的索引端上连接的 Constant 或 Control 被删去时,
索引端符号会自动变为空心的小方框,即变为禁止使用。
也可以按照任何维的组合提取子数组,下面的示意图显示了怎样从一个二维数组中提取一个一维的行或者列数组。
还可以从一个三维数组中提取一个二维数组,方法是禁止两个索引端子,或者通过禁止一个索引端子提取一个一维数组。下图显示了从三维数组提取数组的各种方法。
下面的规则对使用剪切数组进行了规定,
输出对象的维数必须等于被禁止的索引端口的数目。例如
0 个索引端口被禁止=标量元素
1 个索引端口被禁止=二维元素
2 个索引端口被禁止=三维元素
启动的端子所连接的数值必须指定输出元素。
这样,您就可以理解,上图中左下方的例子的作用是,利用 0 列和 3 行的所有元素产生一个一维数组,而右上方的例子的作用是利用第一帧中的所有元素产生一个二维数组。新的第 0 个元素是与原有元素最近的元素。
练习 3-3 使用创建数组功能函数
目的:使用创建数组函数,把一些元素和输出组织成一个更大的数组。
图3-8 练习3-3的面板和框图
1,按照图3-8创建一个前面板。
2,从 Controls?Numeric模板中选择一个数字控制对象放置在前面板中,设置它的标签为 scalar 1。
3,复制并粘贴该数字显示对象,创建两个新的对象,并分别设置它们的标签为 scalar 2 和 scalar 3。
4,创建一个数字控制对象的数组,设置它的标签为 array
1。 复制并粘贴它,创建一个新的数组,设置它的标签为 array 2。
5,在 array 1,scalar 1,scalar 2,scalar 3,array
2 中输入数值 1 到 9。
6,创建流程图。选择 Functions?Array,在流程图中放置一个 Build Array 功能函数。用定位工具增大函数额面积,以容纳 5 个输入。
7,把数组和标量与 Build Array 连接起来。创建输出的一维数组,它由 array 1,scalar 1,scalar 2,array 2,scalar
3 中的元素所组成,如图所示。
8,执行该 VI。可以看到 array 1,scalar 1,scalar 2、
scalar 3,array 2 中的数值出现在同一个一维数组中。
9,保存该 VI 为 LabVIEW\ Activity 目录下的 Build
Array.vi。
练习 3-3 结束 。
3.4 什么是多态化( Polymorphism)?
多态化是指一种函数功能,即可以协调不同格式、维数或者显示的输入数据。大多数 LabVIEW 的函数都是多态化的。例如,
图3-9给出了 Add 函数的一些多态化组合。
图3-9 多态化组合的例子
第一个组合中,两个标量相加,结果还是一个标量。第二个组合中,该标量与数组中的每个元素相加,结果是一个数组。数组是数据的集合。第三个组合中,一个数组的每个元素被加到另一个数组的对应元素中。您还可以使用其他的组合,例如数值簇或者簇数组。
可以把这些准则应用到其他的 G 语言函数或者数据类型。 G
语言函数对于各种情况都具有多态性功能。 有些函数接受数值和布尔输入,而有些函数接受其他任何数据格式的组合。如果您想了解更多关于多态化的知识,请参阅 Online
Reference?Function and VI Reference。
3.5 簇
3.5.1 创建簇控制和显示
在前面板上放置一个簇壳( Cluster shell)就创建了一个簇。
然后你可以将前面板上的任何对象放在簇中。例如数组,你也可以直接从 Control 工具板上直接拖取对象堆放到簇中。 一个簇中的对象必须全部是 Control,或全是 Indicator,不能在同一个簇中组合 Control 与 Indicator,因为簇本身的属性必须是其中之一。一个簇将是 Control 或 Indicator,取决于其内的第一个对象的状态。如果需要可以使用工具重置簇的大小。右图所示是一个含4个 Control 的簇。也可以在流程图上用类似的方法创建簇常数。
如果你要求簇严格地符合簇内对象的大小,可在簇的边界上弹出快速菜单选择自动定义大小( Autosizing)
簇的序( Order)
簇的元素有一个序,它与簇内元素的位置无关。簇内第一个元素的序为 0,第二个是 1,
等等。如果你删除了一个元素,序号将自动调整。如果你想将一个簇与另一个簇连接,这两个簇的序和类型必须同一。
如果想改变簇内元素的序,可在快速菜单中选择 ReOrder Controls In Claster,这时会出现一个窗口,在该窗口内可以修改序。
3.5.2 使用簇与子 VI 传递数据
一个 VI 的连接窗口最大有 28 个端子,如果你不希望使用全部 28 个端子传递数据,这既烦琐又易出错。通过把控制或显示对象捆绑成一个簇的方法,仅使用一个端子就可以实现该功能。
null 捆绑( Bundle)数据
Bundle 功能将分散的元件集合为一个新的簇,或允许你重置一个已有的簇中的元素。可以用位置工具拖曳其图标的右下角以增加输入端子的个数。最终簇的序是取决于被捆绑的输入的顺序。
右图中 Bundle 图标中部的 Claster 端子用于用新元素重置原簇中的元素。
null 分解( Unbundle)簇
Unbundle 功能是 Bundle 的逆过程,它将一个簇分解为若干分离的元件。如果你要对一个簇分解,就必须知道它的元素的个数。
LabVIEW 还提供一种可以根据元素的名字来捆绑或分解簇的方法,稍后介绍。
练习 3-4 簇
目的:学习创建簇、分解簇,再捆绑簇并且在另一个簇中显示其内容。
6.00
Numeric
Boolean1 Boolean 2
Tsinghua
String
Input Cluster
6.00
Numeric
Boolean1 Boolean 2
Tsinghua
String
Output Cluster
STOP
stop
Input Cluster
Output Cluster
Unbundle Bundle
Notstop
图3-10 练习3-4的面板和框图
1.打开前面板,创建一个簇壳( Array & Cluster palette),标签改为 Input Cluster,拖曳至适当大小。
2.在这个簇壳中放置一个数字 Control,两个布尔开关,和一个串 Control。
3.仿照以上步骤,创建 Output Cluster 如上。注意将各 Control 改为相应的 indicator。
4.用快速菜单查看两个簇的序是否一致,若有差别,改之。
5.在前面板上设置一个 [STOP]按钮。注意其缺省值为 FALSE,不要改变它的状态。
6.建立如上面所示的流程图。注意在 [STOP]按钮与循环条件端子之间接入了一个 NOT 函数,因为按钮缺省值为 FALSE,经 NOT 函数后变为 TRUE,这就意味着当按钮状态不变时,循环继续执行,相反一旦按钮动作,
则循环终止。在 6i 版本中这个设置可以简化,不必使用 NOT 函数,直接将 [STOP]按钮与循环条件端子相连,然后用鼠标右键点击循环条件端子,选择 stop if true 即可。结果如右图所示。
7.返回前面板并运行 VI。在输入簇中输入不同的值观察输出。
8.关闭并保存程序。 Cluster Exercise.vi
练习 3-4 结束
3.5.3 用名称捆绑与分解簇
有时你并不需要汇集或分解整个簇,而仅仅需要对其一、两个元素操作。这时你可以用名称来捆绑与分解簇。在 Cluster 工具模板中除了 Bundle 及 Unbundle 功能外,还提供有
Bundle By Name 和 Unbundle By Name 功能。它们允许根据元素的名称(而不是其位置)来查询元素。与 Bundle 不同,使用 Bundle By Name 可以访问你需要的元素,但不能创建新簇;
它只能重置一个已经存在的簇的元素,同时你必须给 Bundle By Name 图标中间的输入端子一个输入以申明要替换其元素的簇。 Unbundle 可返回指定名称的簇元素,不必考虑簇的序和大小。例如,如果你想重置上例中 Boolean 2 的值,就可以使用 Bundle By Name 功能而不必担心簇的序和大小。与此类似如果你要访问串的值,可以使用 Unbundle By Name 功能。
0.00
Numeric
TSINGHUA
String
Cluster Control
0.00
Numeric
ABCD
String
Output Element
ABCD
String Control
图3-11 用名称操作簇
在上面的例子中,Cluster Control 中有两个元素,一个是数据类型(名称是 Numeric),
另一个是字符串型(名称是 String),另一个控制是字符串,ABCD”,框图如右所示,运行该程序,即可将簇内的字符串值重置。 (本例中为了使 Bundle By Name 的输入端由 Numeric
变为 String,需使用快速菜单中的 Select Item 项操作。 )
3.5.4 数组和簇的互换
有时你会发现,将数组变为簇(或者相反)很方便。尤其是因为 LabVIEW 包括的关于数组的操作功能多于簇。例如,前面板上有一个多按钮的簇,你希望颠倒这些按钮值的序。
好了,Reverse 1D Array 功能正好可用,但是它仅可用于数组。这没关系,你可以使用功能 Cluster to Array将簇转换为数组,使用 Reverse 1D Array切换开关的值,最后再利用 Array
String Control
Output Element
String
Cluster Control
to Claster 变换回簇。
3.6 Waveform 数据类型
在数据采集和信号分析中经常要遇到波形数据,在 LabVIEW 6i 中增加了 Waveform 数据类型,使得波形的描述更加简洁。 Waveform 数据类型包含了波形的数据 (Y)、起始时刻 (t0)
和步长Δ X,使用 Waveform 模板的 Build Waveform 函数可以建立一个波形。许多用于数据采集和波形分析的 VI 和函数的缺省状态都接受或返回 Waveform 数据类型。当你将一个
Waveform 数据类型连接到 Waveform Graph 或 Chart 时,会自动画出相应的曲线。 Waveform
数据类型是根据原有的数据类型进一步“打包”组合而成,这种打包也不可避免地带来一些负作用,有时还需要对 Waveform 数据类型“解包” 。有关这一数据类型的函数或 VI 在
Functions? Waveform 和 Analyze 之中。
图3-12 使用 Waveform 的波形发生例子
图3-12是一个使用 Waveform 函数产生正弦波的例子。其中仅仅调用了 Sine
Waveform 一个函数,只要将有关参数指定,就可产生正弦波。 Sine Waveform 实际上是一个子 VI,点击其图标,就可看到下层的程序,还是比较复杂的。在 LabVIEW 6I 以前的版本中用户就需要那样去编程。
第四章 图形显示
4.1 概述
图形显示对于虚拟仪器面板设计是一个重要的内容。 LabVIEW 为此提供了丰富的功能。
在前面几章我们已经接触了这个问题,现在较系统地介绍一下。
我们不从图形的实现方法上去讨论问题,那是计算机图形学的课题。但我们需要从用户的可能的需求角度探求一下,如果你需要做虚拟仪器方面的开发,那么可能遇到些什么图形问题。 LabVIEW 在这方面所做的工作是非常值得借鉴的。
在 LabVIEW 的图形显示功能中 Graph 和 Chart 是两个基本的概念。一般说来 Chart 是将数据源(例如采集得到的数据)在某一坐标系中,实时、逐点地显示出来,它可以反映被测物理量的变化趋势,例如显示一个实时变化的波形或曲线,传统的模拟示波器、波形记录仪就是这样。而 Graph 则是对已采集数据进行事后处理的结果。它先将被采集数据存放在一个数组之中,然后根据需要组织成所需的图形显示出来。它的缺点是没有实时显示,但是它的表现形式要丰富得多。例如采集了一个波形后,经处理可以显示出其频谱图。现在,数字示波器也可以具备类似 Graph 的显示功能。
LabVIEW 的 Graph 子模板中有许多可供选用的控件,其中常用的见下表,
Chart Graph
Waveform(波形)
* *
XY *
Intensity(强度图)
* *
Digital(数字图)
*
3D Surface(三维曲面)
3D Parametric(三维参变量)
*
3D Curve(三维曲线)
由表中可以看出,Chart 方式尽管能实时,直接地显示结果,但其表现形式有限,而 Graph
方式表现形式要远为丰富,但这是以牺牲实时为代价的。在 LabVIEW 6 i 版本中还包含有极坐标等其他图形( Plot),本章不讨论。
4.2 Graph 控件
各种图形都提供了相应的控件,以 Graph 为例介绍。图4-1所示为它的控件。所有这些控件都包含在图形快速菜单的 Visible Items 选项下。
曲线图例可用来设置曲线的各种属性,包括线型(实线、虚线、点划线等),线粗细、
颜色以及数据点的形状等。
图形模板可用来对曲线进行操作,包括移动、对感兴趣的区域放大和缩小等。
光标图例可用来设置光标、移动光标,帮助你用光标直接从曲线上读取感兴趣的数据。
刻度图例用来设置坐标刻度的数据格式、类型(普通坐标或对数坐标),坐标轴名称以及刻度栅格的颜色等。
图 4-1 Graph 的图形控件
4.3 Chart 的独有控件
Chart 的数据并没有事先存在一个数组中,它是实时显示的,为了能够看到先前的数据,
Chart 控件内部含有一个显示缓冲器,其中保留了一些历史数据。这个缓冲器按照先进先出的原则管理,其最大容量是 1024 个数据点。
null 滚动条 (Scrollbar)
它直接对应于显示缓冲器,通过它可以前后观察缓冲器内任何位置的数据。
null 数据显示 (Digital Display)
选中它,可以在图形右上角出现一个数字显示器,这样可以在画出曲线的同时显示当前最新的一个数据值。
null 刷新模式 (Update Mode)
Chart 提供了三种画面的刷新模式,分别是
null Strip Chart Mode(条壮图),它与纸带式图表记录仪类似。曲线从左到右连续绘制,
当新的数据点到达右部边界时,先前的数据点逐次左移。
null Scope Chart Mode(示波器模式),它与示波器类似。曲线从左到右连续绘制,当新的数据点到达右部边界时,清屏刷新,从左边开始新的绘制。它的速度较快。
null Sweep Chart Mode(扫描模式),与示波器模式的不同在于当新的数据点到达右部边界时,不清屏,而是在最左边出现一条垂直扫描线,以它为分界线,将原有曲线逐点向右推,同时在左边画出新的数据点。如此循环下去。
曲线图例
刻度图例
(Scale Legend)
图形模板
(Graph Palette)
光标图例
(Cursor Legend)
标签 (Label)
说明
(Caption)
null 堆叠式图区( Stack Plots)
在相同的纵坐标下,由于各种测量信号的差异,将几条曲线显示在同一个图区有困难时,可以组织出一种纵坐标相同,而有各自横坐标的堆叠式图区。
打开\ LabVIEW\ Examples\ Graphs\ chart.lib 目录的 Charts.vi,那里提供了有关
Chart 的各种形态的例子,以及堆叠式图区的例子
练习 4-1 Chart和 Graph 的比较
目的:创建一个 VI,用 Chart 和 Graph 分别显示 40 个随机数产生的曲线,比较程序的差别。
前面板及流程图如下
图4-2 Chart和 Graph 的比较
显示的运行结果是一样的。但实现方法和过程不同。在流程图中可以看出,Chart 产生在循环内,每得到一个数据点,就立刻显示一个。而 Graph 在循环之外,40 个数都产生之后,跳出循环,然后一次显示出整个数据曲线。从运行过程可以清楚地看到这一点。
值得注意的还有 For 循环执行 40 次,产生的 40 个数据存储在一个数组中,这个数组创建于 For 循环的边界上(使用自动索引功能) 。在 For 循环结束之后,该数组就将被传送到外面的 Graph。仔细看流程图,穿过循环边界的连线在内、外两侧粗细不同,内侧表示浮点数,外侧表示数组。
练习 4-1 结束
4.4 XY 图形控件( XY Graph)
波形图( Waveform Graph)有一个特征,其 X 是测量点序号、时间间隔等,Y 是测量数据值。但是它并不适合描述一般的 Y 值随 X 值变化曲线。适合于这种情况的控件是 XY
Graph。我们通过一个构成利萨育图形的例子来看一下它的使用。我们知道如果控制 XY 方向的两个数组分别按正弦规律变化(假设其幅值、频率都相同),如果它们的相位相同,则利萨育图形是一条 45 度的斜线,当它们之间相位差 90 度时为圆,其他相位差是椭圆。
40
Waveform Chart
100
Waveform Graph
练习4-2 利用 XY Graph 构成利萨育图形。
图4-3 利用 XY Graph 构成利萨育图形
面板和框图如图4-3所示。 面板上除了一个 XY Graph 外,还有一个相位差输入控件。
在框图中使用了两个 Sine Waveform.vi,第一个所有输入参数(包括频率、幅值、相位等)
都使用缺省值,所以其初始相位为0。第二个将其初始相位作为一个控件引到面板上。它们的输出是包括 t0,dt 和 Y 值的簇,但是对于 XY Graph 只需要其中的 Y 数组,因此使用波形函数中的 Get Waveform Components 函数分别提取出各自的 Y 数组,然后再将他们捆绑在一起,连接到 XY Graph 就可以了。当相位置为 45 度时,运行程序,得到如图所示的椭圆。
注意,claster/Bundle
练习 4-2 结束
4.5 强度图形控件( Intensity Graph)
强度图形控件提供了一种在二维平面上表现三维数据的方法。 例如可以用屏幕色彩的亮度来反映来反映一个二维数组元素值的大小。 图4-3就是这样的一个例子。 注意图中的 x、
y 轴刻度对应的是数组行、列的序号。
图4-4 用强度图形表现一个二维数组及其元素值的大小
4.6 数字波形图控件( Digital Waveform Graph)
该控件的例子见图4-5。面板上有一个输入控制,共输入了7个十进制数,还有一个二进制显示对象,显示了这些十进制数对应的二进制数,最右边是一个 Digital Waveform
Graph。注意这个图中数据应当从纵方向读出,在横坐标上的刻度是数据的序号(0到6),
其中最后一个数的序号是6,纵坐标从下向上读是 11111111,第一个数的序号是0,其值从上向下读是 00000001,而第二个数(序号1)是 00000010。
图4-5 数字波形图控件的例图
该程序的框图中值得注意的问题有以下几点,
null 十进制数可以直接送给 Digital Waveform Graph,不必事先转化为二进制数。
null 在送给 Digital Waveform Graph 之前,需要经过一个捆绑( bundle 函数) 。
null 捆绑的顺序是 x0,deltx,输入数据,最后是 Number of Ports。这里的 Number of Ports 将反映二进制的位数或字长,为1时是8位,为2时变为1
6位,余类推。
4.7 3D 图形显示控件( 3D Graph)
二进制显示
Digital Waveform Graph
输入数据
1
Number of Ports
1.0
DeltaX
0.00
X0
第五章 字符串和文件I/O
5.1 字符串
字符串是 ASCII 字符的集合。如同其他语言一样,LabVIEW 也提供了各种处理字符串的功能,如果想获得字符串的例子,可查看 Examples\ General\ strings.llb。下面扼要介绍一些内容。
null 创建字符串控制对象和显示对象
可以在 Controls?String & Table 中看到右边所显示字符串控制对象和显示对象。还可以使用操作工具或者标签工具输入或者改变字符串控制对象中的文本。 用移位工具拖曳字符串控制对象和显示对象的边角可以增大它们的面积。
在这里输入文本字符串 control
练习 5-1 组合字符串
目的:使用一些字符串功能函数将一个数值转换成字符串,并把该字符串和其他一些字符串连接起来组成一个新的输出字符串。
前面板
打开一个新的前面板,按照下图向其中添加对象。
SET
Header
VOLTS
Trailer
5.50
Number
SET 5.5000 VOLTS
输出字符串
16
输出串长度
其中的两个字符串控制对象和数值控制对象可以合并成一个输出字符串并显示在字符串显示器中。数值显示器显示出字符串的长度。
本练习中输出字符串是一个 GPIB( IEEE 488)命令字符串,它可用来与和串口仪器
( RS-232 或者 RS-422)进行通信。
流程图
%s %.4f %s
输出串长度输出字符串
Number
Trailer
Header
null Format Into String 函数( Functions?String)——在本练习中,它用于对数值和字符串进行格式化,使它们成为一个输出字符串。用变形工具可以添加三个加和输入。
null String Length 函数( Functions?String)——在本练习中,它用于返回一个字符串的字节数
null 执行该 VI。注意,Format Into String 功能函数将两个字符串控制对象和数值控制对象组合成一个输出字符串。
null 把该 VI 保存为 Build String.vi,在下一个练习中还将用到这个 VI。
null 字符串格式的设定:选中 Format Into String 函数,单击右键,在快速菜单中选择 Edit
Format String,可分别对个输入的各部分格式做设定。
练习 5-1 结束。
练习 5-2 字符串子集和数值的提取
目的:创建一个字符串的子集,其中含有某个数值的字符串显示,再将它转换成数值。
打开 Examples\General\strings.llb 中的 Parse String.vi。用默认输入值执行该 VI。注意,
DC 的字符串子集被用于输入字符串。还要注意,字符串的数值部分被提取出来,并转换为数值。您可以尝试使用不同的控制数值(记住数组式的字符串是从 0 开始进行编号),或者您可以返回到流程图,查看怎样从输入字符串中提取出其中的元素。
String Subset 函数( Functions?String)——在本练习中,它用于返回偏移地址开始的子字符串以及字节数。第一个偏移地址是 0。
很多情况下,必须把字符串转换成数值,例如需要将从仪器中得到的数据字符串转换成数值。
Scan From String 函数( Functions?String)——在这个例子中,它用于扫描字符串,并将有效的数值( 0 到 9,正负,e,E 和分号)转换成数值。如果连接了一个格式字符串,它将根据字符串指定的格式进行转换,否则将进行默认格式的转换。
该函数从偏移地址的 string 处开始扫描。第一个字符的偏移地址是 0。这个函数在已知头长度(本例中是 VOLTS DC)时或者字符串只含有有效字符时很有用。
选择 File?Close,关闭该 VI。注意不要保存它。
练习 5-2 结束。
5.2 文件的输入 /输出( I/O)
文件 I/O 功能函数是一组功能强大,伸缩性强的文件处理工具。 它们不仅可以读写数据,
还可以移动、重命名文件与目录。创建电子表格格式的、由可读的 ASCII 文本组成的文件,
以及为了提高读写速度和压缩率采用二进制的格式写入数据。
可以采用下面三种文件格式存储或者获得数据,
null ASCII 字节流——如果希望让其他的软件(譬如字处理程序或者电子表格程序)也可以访问数据,就需要将数据存储为 ASCII 格式。为此,您需要把所有数据都转换为 ASCII
字符串。
null 数据记录文件——这种文件采用的是只有 G 语言可以访问的二进制格式。 数据记录文件类似于数据库文件,因为它可以把不同的数据类型存储到同一个文件记录中。
null 二进制字节流——这种文件的格式是最紧凑、最快速地存储文件的格式。您必须把数据转换成二进制字符串的格式,还必须清楚地知道在对文件读写数据时采用的是哪种数据格式。
因为 ASCII 字节流格式是最常用的数据文件格式,所以本节着重介绍这种格式。如果您想获得关于文件 I/O 的例子,请参考 Examples\ File。
5.2.1 文件 I/O 功能函数
大多数的文件 I/O 操作都包括三个基本的步骤:打开一个已有的文件或者新建一个文件;对文件进行读写;关闭文件。 LabVIEW 在 Functions? File I/O 中提供了很多有用的工具 VI。本节主要介绍 9 个高级工具 VI,这些工具 VI 可以把错误检查和错误处理等功能与文件 I/O 功能函数结合起来。
以下5个功能从左到右对应于上面5个图标。
null Write To Spreadsheet File VI——用于将由单精度数值组成的一维或者二维数组转换成文本字符串,再将它写入一个新建文件或者已有文件。该 VI 先打开或者新建文件,之后再关闭文件。它可以用于创建能够被大多数电子表格软件读取的文本文件。
null Read From Spreadsheet File VI——用于从某个文件的特定位置开始读取指定个数的行或者列内容,再将数据转换成二维、单精度数组。该 VI 先打开文件,之后再关闭文件。它可以用于读取用文本格式存储的电子表格文件。
null Write Characters To File VI——用于将一个字符串写入一个新建文件或者已有文件。该 VI 打开这个文件、写入数据,再关闭文件。
null Read Characters From File VI——用于从某个文件的特定位置开始读取指定个数的字符。该 VI 先打开文件,之后再关闭文件。
null Read Lines From File VI——用于从某个文件的特定位置开始读取指定个数的行内容。该 VI 先打开文件,之后再关闭文件。
如果想查看其他的文件 I/O 功能函数,请选择 Function?File I/O? Binary File VIs 或者 Function?File I/O?Advanced File Functions。
5.2.2 将数据写入电子表格文件
将数据存储到文件的最常见应用之一是设置文本文件的格式以便在电子表格文件中打开它。大多数电子表格文件用 Tab 键分割各列,而用 EOL(段尾)分隔各行,如下图所示。
用一个电子表格程序(如 Excel)打开该文件可以看到下面这个表格。
练习 5-3 将数据写入电子表格文件
目的:修改一个已有的 VI 以使用文件 I/O 功能函数,以便可以将数据以 ASCII 格式保存到一个新的文件。然后就可以用一个电子表格程序打开该文件。
前面板
打开前面练习中创建的 Graph Waveform Arrays.vi。当调用这个 VI 时,该 VI 将产生两个数据数组,并将它们绘制在一个图区中。您需要对该 VI 进行修改,从而把两个数组写入一个文件,格式是每列含有一个数组。
-0.09
0
Array
1.5
-0.5
0.0
0.5
1.0
1000 10 20 30 40 50 60 70 80 90
Plot 0
Plot 1
Waveform Graph
don't transpose
transpose? (no:F)
流程图
打开 Graph Waveform Arrays.vi 的流程图,按照下图在流程图的右下角添加功能函数。
null Write To Spreadsheet File VI ( Functions?File I/O)用于将二维数组转换成电子表格字符串,再将它写入一个文件。如果没有指定路径名称,
将会弹出一个文件对话框,提示输入文件名。该 VI 将把一维或者二维数组写入文件。这个例子中,因为用的是二维数组,所以无需连接一维输入端子。
transpose? (no:F)
Build Array
0.5
100
50
Waveform Graph
Array
null Boolean 常数 ( Functions?Boolean)用于控制是否在写入数据之前转换成二维数组。
在这个例子中需要对数据进行转换。因为电子表格文件的每列都含有一个数据数组,所以必须先转换成二维数组。
null 返回前面板,执行该 VI。数据数组产生以后,会出现一个文件对话框提示输入新建文件的文件名。输入文件名,并单击 OK。
null 可以尝试选择转换与不转换两种情况运行程序,查看结果差别。
null 保存该 VI 为 Waveform Arrays to File.vi,并关闭该 VI。
现在可以用电子表格软件或者文本编辑器打开或者编辑刚才创建的文件。可以看到两列表格,每列含有 100 个元素。
在这个例子中,直到所有数组都被采集以后,数据才可以被转换或者写入文件。如果需要更大的数据缓存和希望在数据产生后把它们写入到硬盘,就需要使用另外一个文件 I/O VI。
练习 5-3 结束。
练习 5-4 向文件添加数据
目的:创建一个 VI,可以把温度数据以 ASCII 格式添加到某个文件中。该 VI 使用 For 循环产生温度数据,并将它们存储到一个文件中。在每个循环期间,您都要把数据转换成字符串,添加一个逗号作为分隔符,并将字符串添加到文件中。
前面板
打开一个新的前面板,并按照下图放置对象。
20
数据点个数
90.0
70.0
75.0
80.0
85.0
5939
84.96
温度 Chart
new file
append to file?
前面板中包括一个数字式显示器和一个波形图。,数据点个数”控制对象指定了需要采集和写入文件的温度数据的数量。波形图表则用于显示温度曲线。将波形图表的 Y 轴范围设置为 70.0 到 90.0,X 轴范围设置为 0 到 20。
流程图
温度 Chart
append to file?
%f,
数据点个数
null 打开流程图,添加 For 循环并增大它的面积。该 VI 将产生由“数据点个数”控制对象指定的个数的温度数据。
null 在循环中加一个移位寄存器,方法是用鼠标右键单击循环边界,在快捷菜单中选择移位寄存器。这个移位寄存器中将含有文件的路径名。
null 完成对象的连线。
null Empty Path 常数( Functions?File I\ O?File Constants)——用于初始化移位寄存器,以保证需要对文件写入数据时路径都是空的。会出现一个文件对话框提示输入文件名。
null Digital Thermometer VI( Functions?Select a VI… )——返回一个模拟温度测量值(仿真) 。
null Format Into String 函数( Functions?String)——将温度数据转换成字符串,并且在数据后面增加一个逗号。
null Write Characters To File VI( (Functions?File I/O)——用于向文件写入字符串。
null Boolean 常数( Functions?Boolean)用于将 Write Characters To File VI 的 append to
file?输入为 TRUE,这样在循环执行时新的温度数据就会加入到选中的文件中。用操作工具单击这个常数可以将它设置为 TRUE。
null 返回前面板,把“数据点个数”设置为 20,执行该 VI。这时会出现一个文件对话框,
提示输入文件名。输入文件名以后,VI 就会在每个温度数据产生时,将它写入到该文件中。
null 把该 VI 保存为 LabVIEW\ Activity 目录下的 Write Temperature to File.vi。
null 使用任意一个字处理软件,例如 Write for Windows,Teach Text for Macintosh,或者 UNIX 平台下的某个文本编辑器,打开该数据文件查看其内容。您可以看到文件的内容是 20 个用逗号分隔开的数值(准确到小数点后三位) 。
练习 5-4 结束。
练习 5-5 从文件读取数据
目的:创建一个 VI,可以从上一个练习中创建的例子中读取数据,并把这些数据显示在一个波形图形中。必须按照数据保存的格式来读取它,因为原来是用字符串数据类型,把数据保存为 ASCII 格式,那么就必须用一个文件 I/O 函数把数据作为字符串读出。
前面板
打开一个新的前面板,并按照下图放置对象。
87.402344,
86.914062,
86.425781,
85.937500,
85.449219,
85.449219,
84.960937,
84.472656,
83.984375,
83.984375,
83.984375,
83 984375
从文件读字符串
100.0
50.0
60.0
70.0
80.0
90.0
100 1 2 3 4 5 6 7 8 9
温度 Graph
前面板中包括一个字符串显示对象和一个波形图。“从文件读字符串“显示对象将从上个练习创建的文件中读出用逗号分隔开的温度数据。波形图则用于显示温度曲线。
流程图
Read Characters From File.vi
温度 Graph
从文件读字符串
null Read Characters From File VI( Functions?File I/O)——用于从文件中读取数据,以及输入字符串中的信息。如果没有指定路径名称,将出现一个文件对话框提示您输入文件名。在这个例子中,无需判断需要读取的字符的个数,因为文件的字符数比默认的 512 要少。要从文件中读取数据,必须知道数据的存储方式。如果知道了文件的长度,就可以使用 Read Characters From File VI 读取指定个数的字符。
null Extract Numbers VI (Examples\ General\ strings.llb)——用于提取由逗号、分行符号、非数值字符等分隔开的数据组成的 ASCII 字符串,并将它们转换成数值数组。
null 返回前面板,执行该 VI。将出现一个文件对话框,在其中选择刚才保存的数据文件,
您可以看到图形中显示的数据与 Write Temperature to File VI 例子中显示的一样。
null 保存该 VI 为 Temperature from File.vi,并关闭它。
练习 5-5 结束。
5.3 数据记录文件( datalog file)
上面提供的例子说明了处理 ASCII 字符格式存储的数据的文件的简单方法。 在需要创建供其他软件(如电子表格软件)访问的文件时这种方法很有用。另外一种是称为数据记录文件( datalog file)的数据格式。它与数据库文件有类似之处,文件是由记录组成的,一个文件的所有记录有相同的结构和长度。访问该文件是可以以记录为单位,并且可直接访问文件中的任意一个记录。记录本身的数据结构可由用户自己定义,一个记录内可容纳不同的数据类型,它就像一个簇一样。
如果要用 VI 获得数据,您可能不想把数据写入到 ASCII 文件中,因为把数据和字符串之间相互转换非常花费时间。例如,把一个二维的字符转换成一个具有电子表格格式的字符串(具有标题和时间标记)也是一个非常复杂的操作。如果不需要把文件存储成可供别的软件访问的格式,您可以把数据输出到一个数据记录文件。使用这种格式时,把数据写入到文件的操作变得非常简单,这也使得读写操作的速度更快。它还可以简化数据采集的工作,因为您可以把初始的数据块作为一个日志或者记录读取,而无需了解其中含有多少数据。 G 语言会记录数据的数量,用于对每个数据记录文件的记录。
Write Datalog File 示例(位于 Examples\ File\ datalog.llb)创建了一个新的数据记录文件,并把指定数目的数据写入该文件。每个记录都是一个由一个字符串和一个单精度数据数组构成的簇。
要读取一个数据记录文件,您采用的格式必须与对该文件写入数据时所用格式相同。 Read
Datalog File示例将从 Write Datalog File示例创建的数据记录文件中一次读取一个记录。
读出的每个记录都是一个由一个字符串和一个单精度数据数组构成的簇。
第六章 数据采集
6.1 概述
在计算机广泛应用的今天,数据采集的重要性是十分显著的。它是计算机与外部物理世界连接的桥梁。各种类型信号采集的难易程度差别很大。实际采集时,噪声也可能带来一些麻烦。数据采集时,有一些基本原理要注意,还有更多的实际的问题要解决。
6.1.1 采样频率、抗混叠滤波器和样本数。
假设现在对一个模拟信号 x(t) 每隔Δ t 时间采样一次。时间间隔Δ t 被称为采样间隔或者采样周期。它的倒数 1/Δ t 被称为采样频率,单位是采样数 /每秒。 t=0,Δ t,2Δ t,3
Δ t ……等等,x(t)的数值就被称为采样值。所有 x(0),x(Δ t),x(2Δ t )都是采样值。这样信号 x(t)可以用一组分散的采样值来表示,
下图显示了一个模拟信号和它采样后的采样值。采样间隔是Δ t,注意,采样点在时域上是分散的。
图 6-1 模拟信号和采样显示
如果对信号 x(t)采集 N 个采样点,那么 x(t)就可以用下面这个数列表示,
这个数列被称为信号 x(t)的数字化显示或者采样显示。注意这个数列中仅仅用下标变量编制索引,而不含有任何关于采样率(或Δ t)的信息。所以如果只知道该信号的采样值,并不能知道它的采样率,缺少了时间尺度,也不可能知道信号 x(t)的频率。
根据采样定理,最低采样频率必须是信号频率的两倍。 反过来说,如果给定了采样频率,
那么能够正确显示信号而不发生畸变的最大频率叫做恩奎斯特频率,它是采样频率的一半。
如果信号中包含频率高于奈奎斯特频率的成分,信号将在直流和恩奎斯特频率之间畸变。图
6-2显示了一个信号分别用合适的采样率和过低的采样率进行采样的结果。
采样率过低的结果是还原的信号的频率看上去与原始信号不同。 这种信号畸变叫做混叠
( alias) 。出现的混频偏差( alias frequency)是输入信号的频率和最靠近的采样率整数倍的差的绝对值。
图 6-2 不同采样率的采样结果
图6-3给出了一个例子。假设采样频率 fs 是 100HZ,,信号中含有 25,70,160、
和 510 Hz 的成分。
图6-3 说明混叠的例子
采样的结果将会是低于奈奎斯特频率( fs/2=50 Hz)的信号可以被正确采样。而频率高于
50HZ 的信号成分采样时会发生畸变。分别产生了 30,40 和 10 Hz 的畸变频率 F2,F3 和 F4。
计算混频偏差的公式是,
混频偏差= ABS(采样频率的最近整数倍-输入频率)
其中 ABS 表示“绝对值”,例如,
混频偏差 F2 = |100 – 70| = 30 Hz
混频偏差 F3 = |(2)100 – 160| = 40 Hz
混频偏差 F4 = |(5)100 – 510| = 10 Hz
为了避免这种情况的发生,通常在信号被采集( A/D)
之前,经过一个低通滤波器,将信号中高于奈奎斯特频率的信号成分滤去。在图6-3的例子中,这个滤波器的截止频率自然是
a 足够的采样率下的采样结果
b 过低采样率下的采样结果
25HZ。这个滤波器称为 抗混叠滤波器
采样频率应当怎样设置呢?也许你可能会首先考虑用采集卡支持的最大频率。但是,较长时间使用很高的采样率可能会导致没有足够的内存或者硬盘存储数据太慢。 理论上设置采样频率为被采集信号最高频率成分的2倍就够了,实际上工程中选用
5~10倍,有时为了较好地还原波形,甚至更高一些。
通常,信号采集后都要去做适当的信号处理,例如 FFT 等。
这里对样本数又有一个要求,一般不能只提供一个信号周期的数据样本,希望有5~10个周期,甚至更多的样本。并且希望所提供的样本总数是整周期个数的。这里又发生一个困难,有时我们并不知道,或不确切知道被采信号的频率,因此不但采样率不一定是信号频率的整倍数,也不能保证提供整周期数的样本。我们所有的仅仅是一个时间序列的离散的函数 x(n)和采样频率。
这是我们测量与分析的唯一依据。
6.1.2 数据采集系统的构成
图6-4 数据采集系统结构
上图表示了数据采集的结构。在数据采集之前,程序将对采集板卡初始化,板卡上和内存中的 Buffer 是数据采集存储的中间环节。需要注意的两个问题是:是否使用 Buffer?是否使用外触发启动、停止或同步一个操作。
缓冲( Buffers)
这里的缓冲指的是 PC 内存的一个区域(不是数据采集卡上的 FIFO 缓冲),它用来临时存放数据。例如,你需要采集每秒采集几千个数据,在一秒内显示或图形化所有数据是困难的。但是将采集卡的数据先送到 Buffer,你就可以先将它们快速存储起来,稍后再重新找回它们显示或分析。 需要注意的是 Buffer 与采集操作的速度及容量有关。 如果你的卡有 DMA
性能,模拟输入操作就有一个通向计算机内存的高速硬件通道,这就意味着所采集的数据可以直接送到计算机的内存。
不使用 Buffer 意味着对所采集的每一个数据你都必须及时处理(图形化、分析等),因为这里没有一个场合可以保持你着手处理的数据之前的若干数据点。
下列情况需要使用 Buffer I/O,
null 需要采集或产生许多样本,其速率超过了实际显示、存储到硬件,或实时分析的速度。
null 需要连续采集或产生 AC 数据( >10 样本/秒),并且要同时分析或显示某些数据。
null 采样周期必须准确、均匀地通过数据样本。
下列情况可以不使用 Buffer I/O,
null 数据组短小,例如每秒只从两个通道之一采集一个数据点。
null 需要缩减存储器的开支。
触发( Triggering)
触发涉及初始化,终止或同步采集事件的任何方法。 触发器通常是一个数字或模拟信号,
其状态可确定动作的发生。软件触发最容易,你可以直接用软件,例如使用布尔面板控制去启动 /停止数据采集。硬件触发让板卡上的电路管理触发器,控制了采集事件的时间分配,
有很高的精确度。硬件触发可进一步分为外部触发和内部触发。当某一模入通道发生一个指定的电压电平时,让卡输出一个数字脉冲,这是内部触发。采集卡等待一个外部仪器发出的数字脉冲到来后初始化采集卡,这是外部触发。许多仪器提供数字输出(常称为,trigger
out” )用于触发特定的装置或仪器,在这里,就是数据采集卡。
下列情况使用软件触发,
null 用户需要对所有采集操作有明确的控制,并且
null 事件定时不需要非常准确。
下列情况使用硬件触发,
null 采集事件定时需要非常准确。
null 用户需要削减软件开支。
null 采集事件需要与外部装置同步。
后面可以看到怎样使用采集的 VI 程序设置有 Buffer 及无 Buffer 的 I/O 操作,以及设置触发的类型。
6.1.3 模入信号类型
数据采集前,必须对所采集的信号的特性有所了解,因为不同信号的测量方式和对采集系统的要求是不同的,只有了解被测信号,才能选择合适的测量方式和采集系统配置。
任意一个信号是随时间而改变的物理量。一般情况下,信号所运载信息是很广泛的,
比如:状态( state),速率 (rate)、电平 (level)、形状 (shape)、频率成分 (frequency
content)。根据信号运载信息方式的不同,可以将信号分为模拟或数字信号。数字 (二进制 )
信号分为开关信号和脉冲信号。模拟信号可分为直流、时域、频域信号,如图 6-5 所示。
图 6-5 信号分类
数字信号
第一类数字信号是开 -关信号。一个开 -关信号运载的信息与信号的瞬间状态有关。 TTL
信号就是一个开 -关信号,一个 TTL 信号如果在 2.0 到 5.0V 之间,就定义它为逻辑高电平,
如果在 0 到 0.8V 之间,就定义为逻辑低电平。
第二类数字信号是脉冲信号。这种信号包括一系列的状态转换,信息就包含在状态转化发生的数目、转换速率、一个转换间隔或多个转换间隔的时间里。安装在马达轴上的光学编码器的输出就是脉冲信号。有些装置需要数字输入,比如一个步进式马达就需要一系列的数字脉冲作为输入来控制位置和速度。
模拟直流信号
模拟直流信号是静止的或变化非常缓慢的模拟信号。 直流信号最重要的信息是它在给定区间内运载的信息的幅度。常见的直流信号有温度、流速、压力、应变等。采集系统在采集模拟直流信号时,需要有足够的精度以正确测量信号电平,由于直流信号变化缓慢,用软件计时就够了,不需要使用硬件计时。
模拟时域信号
模拟时域信号与其他信号不同在于,它在运载信息时不仅有信号的电平,还有电平随时间的变化。在测量一个时域信号时,也可以说是一个波形,需要关注一些有关波形形状的特性,比如斜度、峰值等。为了测量一个时域信号,必须有一个精确的时间序列,序列的时间间隔也应该合适,以保证信号的有用部分被采集到。要以一定的速率进行测量,这个测量速率要能跟上波形的变化。用于测量时域信号的采集系统包括一个 A/ D、一个采样时钟和一个触发器。 A/ D 的分辨率要足够高,保证采集数据的精度,带宽要足够高,用于高速率采样;精确的采样时钟,用于以精确的时间间隔采样;触发器使测量在恰当的时间开始。存在许多不同的时域信号,比如心脏跳动信号、视频信号等,测量它们通常是因为对波形的某些方面特性感兴趣。
模拟频域信号
模拟频域信号与时域信号类似,然而,从频域信号中提取的信息是基于信号的频域内容,
而不是波形的形状,也不是随时间变化的特性。用于测量一个频域信号的系统必须有一个 A
/ D、一个简单时钟和一个用于精确捕捉波形的触发器。系统必须有必要的分析功能,用于从信号中提取频域信息。为了实现这样的数字信号处理,可以使用应用软件或特殊的 DSP
硬件来迅速而有效地分析信号。模拟频域信号也很多,比如声音信号、地球物理信号、传输信号等。
上述信号分类不是互相排斥的。一个特定的信号可能运载有不只一种信息,可以用几种方式来定义信号并测量它,用不同类型的系统来测量同一个信号,从信号中取出需要的各种信息。
6.1.4 模入信号的连接方式
一个电压信号可以分为接地和浮动两种类型。测量系统可以分为差分( Differential),
参考地单端( RSE),无参考地单端( NRSE)三种类型。
1.接地信号和浮动信号
接地信号
接地信号,就是将信号的一端与系统地连接起来,如大地或建筑物的地。因为信号用的是系统地,所以与数据采集卡是共地的。接地最常见的例子是通过墙上的接地引出线,如信号发生器和电源。
浮动信号
一个不与任何地(如大地或建筑物的地)连接的电压信号称为浮动信号,浮动信号的每个端口都与系统地独立。 一些常见的浮动信号的例子有电池,热电偶,变压器和隔离放大器。
2.测量系统分类
差分测量系统
差分测量系统中,信号输入端分别与一个模入通道相连接。具有放大器的数据采集卡可配置成差分测量系统。图 6-6 描述了一个 8 通道的差分测量系统,用一个放大器通过模拟多路转换器进行通道间的转换。标有 AIGND(模拟输入地)的管脚就是测量系统的地。
图 6-6 差分测量系统
一个理想的差分测量系统仅能测出( +)和( -)输入端口之间的电位差,完全不会测量到共模电压。然而,实际应用的板卡却限制了差分测量系统抵抗共模电压的能力,数据采集卡的共模电压的范围限制了相对与测量系统地的输入电压的波动范围。 共模电压的范围关系到一个数据采集卡的性能,可以用不同的方式来消除共模电压的影响。如果系统共模电压超过允许范围,需要限制信号地与数据采集卡的地之间的浮地电压,以避免测量数据错误。
参考地单端测量系统 (RSE)
一个 RSE 测量系统,也叫做接地测量系统,被测信号一端接模拟输入通道,另一端接系统地 AIGND。图 6-7 描绘了一个 16 通道的 RSE 测量系统。
无参考地单端测量系统 (NRSE)
在 NRSE 测量系统中,信号的一端接模拟输入通道,另一端接一个公用参考端,但这个参考端电压相对于测量系统的地来说是不断变化的。图 6-8 说明了一个 NRSE 测量系统,其中 AISENSE 是测量的公共参考端,AIGND 是系统的地 。
图 6-7 参考地单端测量系统
图 6-8 无参考地单端测量系统
3.选择合适的测量系统
两种信号源和三种测量系统一共可以组成六种连接方式,
接地信号 浮动信号
DEF
* *
RSE
**
NRSE
* *
其中,不带 *号的方式不推荐使用。一般说来,浮动信号和差动连接方式可能较好。但实际测量时还要看情况而定。
测量接地信号
测量接地信号最好采用差分或 NRSE 测量系统。如果采用 RSE 测量系统时,将会给测量结果带来较大的误差。图 6-9 展示了用一个 RSE 测量系统去测量一个接地信号源的弊端。
在本例中,测量电压 Vm 是测量信号电压 Vs 和电位差 DVg 之和,其中 DVg 是信号地和测量地之间的电位差,这个电位差来自于接地回路电阻,可能会造成数据错误。一个接地回路通常会在测量数据中引入频率为电源频率的交流和偏置直流干扰。 一种避免接地回路形成的办法就是在测量信号前使用隔离方法,测量隔离之后的信号。
图 6-9 RSE 测量系统引入接地回路电压
如果信号电压很高并且信号源和数据采集卡之间的连接阻抗很小,也可以采用 RSE 系统,因为此时接地回路电压相对于信号电压来说很小,信号源电压的测量值受接地回路的影响可以忽略。
测量浮动信号
可以用差分,RSE,NRSE 方式测量浮动信号。在差分测量系统中,应该保证相对于测量地的信号的共模电压在测量系统设备允许的范围之内。如果采用差分或 NRSE 测量系统,
放大器输入偏置电流会导致浮动信号电压偏离数据采集卡的有效范围。为了稳住信号电压,
需要在每个测量端与测量地之间连接偏置电阻,如图 6-10 所示。这样就为放大器输入到放大器的地提供了一个直流通路。这些偏置电阻的阻值应该足够大,这样使得信号源可以相对于测量地浮动。对低阻抗信号源来说,10kΩ到 100kΩ的电阻比较合适。
图 6-10 增加偏置电阻
如果输入信号是直流,就只需要用一个电阻将( -)端与测量
系统的地连接起来。然而如果信号源的阻抗相对较高,从免除干扰的角度而言,这种连接方式会导致系统不平衡。在信号源的阻抗足够高的时候,应该选取两个等值电阻,一个连接信号高电平( +)到地,一个连接信号低电平( -)到地。如果输入信号是交流,就需要两个偏置电阻,以达到放大器的直流偏置通路的要求。
总的来说,不论测接地还是浮动信号,差分测量系统是很好的选择,因为它不但避免了接地回路干扰,还避免了环境干扰。相反的,RSE 系统却允许两种干扰的存在,在所有输入信号都满足以下指标时,可以采用 RSE 测量方式:输入信号是高电平(一般要超过 1V) ;
连线比较短 (一般小于 5 米) 并且环境干扰很小或屏蔽良好; 所有输入信号都与信号源共地。
当有一项不满足要求时,就要考虑使用差分测量方式。
另外需要明确信号源的阻抗。电池,RTD、应变片、热电偶等信号源的阻抗很小,可以将这些信号源直接连接到数据采集卡上或信号调理硬件上。 直接将高阻抗的信号源接到插入式板卡上会导致出错。为了更好的测量,输入信号源的阻抗与插入式数据采集卡的阻抗相匹配。
6.1.5 信号调理
从传感器得到的信号大多要经过调理才能进入数据采集设备,信号调理功能包括放大、
隔离、滤波、激励、线性化等。由于不同传感器有不同的特性,因此,除了这些通用功能,
还要根据具体传感器的特性和要求来设计特殊的信号调理功能。 下面仅介绍信号调理的通用功能。
1.放大
微弱信号都要进行放大以提高分辨率和降低噪声,使调理后信号的电压范围和 A/D 的电压范围相匹配。 信号调理模块应尽可能靠近信号源或传感器,使得信号在受到传输信号的环境噪声影响之前已被放大,使信噪比得到改善。
2.隔离
隔离是指使用变压器、光或电容耦合等方法在被测系统和测试系统之间传递信号,避免直接的电连接。使用隔离的原因由两个:一是从安全的角度考虑;另一个原因是隔离可使从数据采集卡读出来的数据不受地电位和输入模式的影响。 如果数据采集卡的地与信号地之间有电位差,而又不进行隔离,那么就有可能形成接地回路,引起误差。
3.滤波
滤波的目的是从所测量的信号中除去不需要的成分。大多数信号调理模块有低通滤波器,用来滤除噪声。通常还需要抗混叠滤波器,滤除信号中感兴趣的最高频率以上的所有频率的信号。某些高性能的数据采集卡自身带有抗混叠滤波器。
4.激励
信号调理也能够为某些传感器提供所需的激励信号,比如应变传感器、热敏电阻等需要外界电源或电流激励信号。很多信号调理模块都提供电流源和电压源以便给传感器提供激励。
5.线性化
许多传感器对被测量的响应是非线性的,因而需要对其输出信号进行线性化,以补偿传感器带来的误差。但目前的趋势是,数据采集系统可以利用软件来解决这一问题。
6.数字信号调理
即使传感器直接输出数字信号,有时也有进行调理的必要。其作用是将传感器输出的数字信号进行必要的整形或电平调整。大多数数字信号调理模块还提供其他一些电路模块,使得用户可以通过数据采集卡的数字 I/O 直接控制电磁阀、电灯、电动机等外部设备。
6.1.6 数据采集 (DAQ)卡
1.数据采集卡的功能
一个典型的数据采集卡的功能有模拟输入、模拟输出、数字 I/O、计数器 /计时器等,这些功能分别由相应的电路来实现。
模拟输入是采集最基本的功能。它一般由多路开关( MUX),放大器、采样保持电路以及 A/D 来实现,通过这些部分,一个模拟信号就可以转化为数字信号。 A/D 的性能和参数直接影响着模拟输入的质量,要根据实际需要的精度来选择合适的 A/D。
模拟输出通常是为采集系统提供激励。输出信号受数模转换器( D/A)的建立时间、转换率,分辨率等因素影响。 建立时间和转换率决定了输出信号幅值改变的快慢。 建立时间短、
转换率高的 D/A 可以提供一个较高频率的信号。 如果用 D/A 的输出信号去驱动一个加热器,
就不需要使用速度很快的 D/A,因为加热器本身就不能很快地跟踪电压变化。应该根据实际需要选择 D/A 的参数指标。
数字 I/O 通常用来控制过程、产生测试信号、与外设通信等。它的重要参数包括:数字口路数( line),接收 (发送 )率、驱动能力等。如果输出去驱动电机、灯、开关型加热器等用电器,就不必用较高的数据转换率。路数要能同控制对象配合,而且需要的电流要小于采集卡所能提供的驱动电流。但加上合适的数字信号调理设备,仍可以用采集卡输出的低电流的 TTL 电平信号去监控高电压、大电流的工业设备。数字 I/O 常见的应用是在计算机和外设如打印机,数据记录仪等之间传送数据。 另外一些数字口为了同步通信的需要还有,握手”
线。路数、数据转换速率,“握手”能力都是应理解的重要参数,应依据具体的应用场合而选择有合适参数的数字 I/O。
许多场合都要用到计数器,如定时、产生方波等。计数器包括三个重要信号:门限信号、
计数信号、输出。门限信号实际上是触发信号——使计数器工作或不工作;计数信号也即信号源,它提供了计数器操作的时间基准;输出是在输出线上产生脉冲或方波。计数器最重要的参数是分辨率和时钟频率,高分辨率意味着计数器可以计更多的数,时钟频率决定了计数的快慢,频率越高,计数速度就越快。
2.数据采集卡的软件配置
一般说来,数据采集卡都有自己的驱动程序,该程序控制采集卡的硬件操作,当然这个驱动程序是由采集卡的供应商提供,用户一般无须通过低层才能与采集卡硬件打交道。
NI 公司还提供了一个数据采集卡的配置工具软件—— Measurement & Automation
Explorer,它可以配置 NI 公司的软件和硬件,比如执行系统测试和诊断、增加新通道和虚拟通道、设置测量系统的方式、察看所连接的设备等。
6.1.7 多通道的采样方式
多数通用采集卡都有多个模入通道,但是并非每个通道配置一个 A/D,而是大家共用一套 A/D,在 A/D 之前的有一个多路开关( MUX),以及放大器( AMP),采样保持器( S/H)
等。通过这个开关的扫描切换,实现多通道的采样。多通道的采样方式有三种:循环采样、
同步采样和间隔采样。在一次扫描( scan)中,数据采集卡将对所有用到的通道进行一次采样,扫描速率( scan rate)是数据采集卡每秒进行扫描的次数。
当对多个通道采样时,循环采样是指采集卡使用多路开关以某一时钟频率将多个通道分别接入 A/D 循环进行采样。如图 6-11 给出两个通道循环采样的示意图。此时,所有的通道共用一个 A/D 和 S/H 等设备,比每个通道分别配一个 A/D 和 S/H 的方式要廉价。循环采样的缺点在于不能对多通道同步采样,通道的扫描速率是由多路开关切换的速率平均分配给每个通道的。因为多路开关要在通道间进行切换,对两个连续通道的采样,采样信号波形会随着时间变化,产生通道间的时间延迟。如果通道间的时间延迟对信号的分析不很重要时,使用循环采样是可以的。
图 6-11 循环采样
当通道间的时间关系很重要时,就需要用到同步采样方式。支持这种方式的数据采集卡每个通道使用独立的放大器和 S/H 电路,经过一个多路开关分别将不同的通道接入 A/D 进行转换。图 6-12 给出两个通道同步采样的示意图。还有一种数据采集卡,每个通道各有一个独立的 A/D,这种数据采集卡的同步性能更好。但是成本显然更高。
图6-12 同步采样
假定用四个通道来采集均为 50kHz 的周期信号(其周期是 20μ s),数据采集卡的采样速率设为 200kHz。则采样间隔为 5μ s( 1/200kHz) 。如果用循环采样则每相邻两个通道之间的采样信号的时间延迟为 5μ s( 1/200kHz),这样通道 1 和通道2之间就产生了 1/4 周期的相位延迟,而通道 1 和通道4之间的信号延迟就达 15μ s,折合相位差是 270
0
。一般说来这是不行的。
为了改善这种情况。而又不必付出像同步采用采样那样大的代价。就有了如下的间隔扫描( interval scanning)方式。
在这种方式下,用通道时钟控制通道间的时间间隔,而用另一个扫描时钟控制两次扫描过程之间的间隔。通道间的间隔由实际上由采集卡的最高采样速率决定,可能是微秒、甚至纳秒级的,效果接近于同步扫描。间隔扫描适合缓慢变化的信号,比如温度和压力。假定一个 10 通道温度信号的采集系统,用间隔采样,设置相邻通道间的扫描间隔为 5μ s,每两次扫描过程的间隔是 1s,这种方法提供了一个以 1Hz 同步扫描 10 通道的方法,如图6 -13所示。 1 通道和 10 通道扫描间隔是 45μ s,相对于 1Hz 的采样频率是可被忽略的。对一般采集系统来说,间隔采样是性价比较高的一种采样方式。
图6-13 间隔采样
NI 公司的数据采集卡可以使用内部时钟来设置扫描速率和通道间的时间间隔。多数数据采集卡根据通道时钟( channel clock )按顺序扫描不同的通道,控制一次扫描过程中相邻通道间的时间间隔,而用扫描时钟( scan clock)来控制两次扫描过程的间隔。通道时钟要比扫描时钟快,通道时钟速率越快,在每次扫描过程中相邻通道间的时间间隔就越小。
对于具有扫描时钟和通道时钟的数据采集卡,可以通过把扫描速率( scan rate)设为 0,
使用 AI Config VI 的 interchannel delay 端口来设置循环采样速率。 LabVIEW 默认的是 scan
clock,换句话来说,当选择好扫描速率时,LabVIEW 自动选择尽可能快的通道时钟速率,
大多数情况下,这是一种比较好的选择。图 6-14 说明循环采样和间隔采样的不同。
图 6-14 间隔采样与循环采样比较
6.1.8 LabVIEW 数据采集模块的分类
LabVIEW 中对于数据采集模块按照难易程度做了分类,图 6-15 以模入为例表明了工具栏中各种类型的模入模块。
图 6-15 模入的各种模块
简易模入 VIs (Ease Analog VIs)
该行的四个模块执行简单的模入操作。它们可以作为单独的 VI,也可以作为 subVI 来使用。这些模块可以自动发出错误警告信息,在对话框中你可以选择中断运行或忽略。但是比较复杂的应用需要使用下面的类型。
中级模入 VIs (Intermediate Analog Input VIs)
中级模入在两个地方可以找到,一个如图 6-15 的位置,另一个是包含在下面讨论的通用模入 VIs 中。与简易模入不同的是在那里的一个操作 AI Input,这里细分为 AI Config,AI
Start,AI Read,AI Single Scan 以及 AI Clear。它可以描述更加细致、复杂的操作。
通用模入 VIs ( Analog Input Utility VIs)
这里提供了三个常用的 Vis,AI Read One Scan,AI Waveform Scan,及 AI Continuous
Scan。使用一个 VI 就可以解决一个普通的模入问题,方便但缺乏灵活性。这三个 Vis 是由中级模入构成的。
高级模入 VIs ( Advanced Analog Input VIs)
这些 Vis 是 NI-DAQ 数据采集软件的界面,是上面三种类型 Vis 的基础。一般情况下,
用户不需要直接使用这个功能。
在下面的介绍中我们主要涉及前两项。
6.2 模拟输入( Analog Input)
6.2.1 模入参数说明
为了更好地理解模入,需要了解信号数字化过程中分辨率、范围、增益等参数对采集信号质量的影响。
分辨率( Resolution)
分辨率就是用来进行模数转换的位数,A/D 的位数越多,分辨率就越高,可区分的最小电压就越小。分辨率要足够高,数字化信号才能有足够的电压分辨能力,才能比较好的恢复原始信号。目前分辨率为 8 的采集卡属于较低的,12 位属中档,16位的卡就比较高了。
他们可以分别将模入电压量化为 256,4096,65536 份。
电压范围 (Range)
电压范围由 A/D 能数字化的模拟信号的最高和最低的电压决定。一般情况下,采集卡的电压范围是可调的,所以可选择和信号电压变化范围相匹配的电压范围以充分利用分辨率简易模入 VIs
中级模入 VIs
高级模入 VIs
通用模入 VIs
范围,得到更高的精度。比如,对于一个 3 位的 A/D,在选择 0-10V 范围时,它将 10V 八等分;如果选择范围为 -10V 到 +10V,同一个 A/D 就得将 20V 分为 8 等分,能分辨的最小电压就从 1.25V 上升到 2.50V,这样信号复原的效果就更差了。
增益( Gain)
增益主要用于在信号数字化之前对衰减的信号进行放大。使用增益,可以等效地降低
A/D 的输入范围,使它能尽量将信号分为更多的等份,基本达到满量程,这样可以更好地复原信号。因为对同样的电压输入范围,大信号的量化误差小,而小信号时量化误差大。当输入信号不接近满量程时,量化误差会相对加大。如:输入只为满量程的 1/ 10 时,量化误差相应扩大 10 倍。一般使用时,要通过选择合适的增益,使得输入信号动态范围与 A/D 的电压范围相适应。当信号的最大电压加上增益后超过了板卡的最大电压,超出部分将被截断而读出错误的数据。
对于 NI 公司的采集卡选择增益是在 LabVIEW 中通过设置信号输入限制( input limits)
来实现的,LabVIEW 会根据选择的输入限制和输入电压范围的大小来自动选择增益的大小。
一个采集卡的分辨率、范围和增益决定了可分辨的最小电压,它表示为 1LSB。例如,
某采集卡的分辨率为 12 位,范围取 0-10V,增益取 100,则有 1LSB=10V/ (100× 4096)≈24
μ V。这样,在数字化过程中,最小能分辨的电压就为 24μ s。
选择合适的增益和输入范围要与实际被测信号匹配。 如果输入信号的改变量比采集卡的精度低,就可以将信号放大,提高增益。选择一个大的输入范围或降低增益可以测量大范围的信号,但这是以精度的降低为代价的。选择一个小的输入范围或提高增益可以提高精度,
但这可能会使信号超出 A/D 允许的电压范围。
在研究采集 VI 之前需要了解如下的几个定义。我们以下图的多通道模入波形采集 AI
Acquire Waveform.vi 为例说明。
device——设备号。在 NI 采集设置工具中设定。该参数告诉 LabVIEW 你使用什么卡,
它可以使采集 VI 自身独立于卡的类型,也就是说,如果你稍后使用了另一种卡,并且赋予它同样的设备号,你的 VI 程序可正常工作而无须修改。
channels——指定数据样本的物理源。例如,一个卡有16个模拟输入 通道,你就可以同时采集16组数据点。在 LabVIEW VI 中,一个 通道 或一组 通道 都用一个字符串来指定。例如,
通道 通道串
通道 5 5
通道 0 到 4 0:4
通道 1,8,以及 10 到 13 1,8,10:13
scan rate(1000 scans/sec)——是在多通道采样时,分配给一个通道得到的样本速率,
缺省值是 1000/秒。
number of samples/ch——每通道要采集的样本数,缺省值是 1000。
high limit——被测信号的最高电平,其缺省值是0。设为缺省值时系统将按照采集卡设置程序 MAX 中的设定处理。
low limit——被测信号的最低电平,其缺省值是0。设为缺省值时系统将按照采集卡设置程序 MAX 中的设定处理。
high limit 和 low limit 的值将决定采集系统的增益。对大多数卡输入信号变化的缺省值是 10V 到 -10V,如果你将其设为 5 到 -5V,则增益为 2。如果你将其设为 1 到 -1V,
则增益为 10。如果你设置一个理论上的增益是得不到支持的,LabVIEW 会自动将其调整到最近的预置值。典型的采集卡所支持的增益值有 0.5,1,2,5,10,20,50,100。
waveforms—— A/D 转换后的输出,是一个二维的 waveform 数组,其每一列对应于一个输入通道,同时包含有反映时间信息的 t0 和Δ t。
LabVIEW 数据采集模块的分类
下面我们将由简到难地介绍有关内容。
6.2.2 简易模入( Ease Analog VIs)
这是 LabVIEW 提供的一组标准的、简单易用的采集 VI。
从左到右,4个 VI 的功能为,
null 从指定通道获得一个样本。
null 从由通道字符串规定的一组通道每通道获得一个样本。 这些样本返回到一个样本数组,顺序由通道号决定。
null 按指定的采样率由一个通道得到一个波形(一组覆盖一个周期的样本),这些样本返回到一个 wareform 数组。
null 从由通道字符串规定的每个通道获得一个波形。 这些样本返回到一个波形的2维数组,顺序由通道号和采样周期决定。 通道数据的每个点占1列,时间增量由行决定。
练习 6-1
目的:采集一个直流电压信号
1.00.0
0.2
0.4 0.6
0.8
Meter
Meter
0
1
1.准备一个直流电源(例如 0.5V)作为信号源连接到数据采集卡的 0 通道模入端。
2.构造前面板和框图如上面所示。
3.运行程序。可得到 Meter 指示 0.5V。
练习 6-1 结束
练习 6-2
目的:多通道数据采集
1.准备一个方波信号源和一个正弦波信号源。分别连接到模入通道0和1。
2.设置前面板与框图如上。
3.设置 scan 速率、通道号、每通道样本数如前面板所示。
4.运行该程序。
5.保存为 Acquire Multiple Channels.vi。
6.该程序是无缓冲、软件触发的。
注意:这里使用的 AI Acquire Waveform.vi 具有多态性,它的输出可以是 Waveform,也可以是 Array,前者可直接与 Graph 连接,后者如果直接要与 Graph 连接麻烦一些。 在 LabVIEW
6I 以前的版本中只有后者。用后者编写这个程序的框图如下,
增加的步骤包括,
7.在框图上调出 AI Acquire Waveform.vi 的快速菜单,选择 Select Type >Scaled Array。
8.在前面板上的 graph 上用快捷菜单选择 Transpose Array。因为 AI Sample Channel
功能返回的 2D 数组是每列反映一个通道的电压,而在一般情况下 graph 图形是行对列,所以需要对数组做一次转置,以使 Y 轴表示电压值。
9.在框图上将起始时刻、实际采样周期的倒数和采样数据使用 Bundle 功能捆绑成一个数组,送给 graph。注意捆绑的顺序是 I32,SGL 和数组,如果变为 I32、数组和 SGL,可能出错。
练习 6-2 结束
6.2.3 中级模入 Analog Input
上面介绍的简单模入的基本局限是执行采集任务的庸余。例如,你每一次调用 AI
Sample Channel,都必须为特定类型的测量设置硬件,告诉它采样率等。显然,如果你要反复采集大量的样本,你未必需要在每一次重复时都去设置测量。 一个典型的情况是连续采集,
需要在程序中采用循环结构,按照简单模入,每次采集前都在设置参数,不仅多余,而且造
0
扫描速率每通道样本数
Waveform Graph
AI Acquire Waveforms.vi
成了采集过程的不连续。
中级模入有更好的功能与灵活性,可以更有效地开发你的应用。它的特点包括控制内部采样率,使用外部触发,执行连续外部触发等。下面我们将仔细描述它的各种 VI,应该注意其大量输入、输出端子中的部分内容一般是不必理会的。有效地使用这些 VI 只需要关注你需要的端子。在大多数情况下,你不需要为在 help 中解释的端子的设置烦恼。
null Analog Input
AI Config 对指定的通道设置模入操作,包括硬件、计算机内 buffer 的分配。常用的端子有,
null Device——采集卡的设备号。
null Channel——指定模入通道号的串数组。
null Intput limit——指定输入信号的范围达到调节硬件增益的目的。
null Buffer size——单位是 scan,控制用于采集数据的 AI Config 占用计算机内存的大小。
null Interchannel delay——扫描间隔设置。缺省值为 -1,当选用缺省值时,系统按照采集卡的最高扫描速率(一般为几微秒),再加上系统消耗 10 微秒,来设置扫描间隔,对 MIO-16-E-4 卡来说,约为 14 微秒。用户也可以自行设置这个值,实验表明,
对 MIO-16-E-4 卡最小可设到 2~3 微秒。
AI Start 启动带缓冲的模入操作。它控制数据采集速率,采集点的数目,及使用任何硬件触发的选择。它的两个重要输入是,
null Scan rate(scan/sec)——对每个通道采集的每秒扫描次数。
null Number of scans to acquire——对通道列表的扫描次数。??
AI Read——从被 AI Config 分配的缓冲读取数据。它能够控制由缓冲读取的点数,读取数据在缓冲中的位置,以及是否返回二进制数或标度的电压数。 它的输出是一个2维数组,
其中每一列数据对应于通道列表中的一个通道。
AI Single Scan——返回一个扫描数据。它的电压数据输出是由通道列表中的每个通道读出的电压数据。使用这个 VI 仅与 AI Config 有关联,不需要 AI Start 和 AI Read。
AI Clear——清除模入操作、计算机中分配的缓冲、释放所有数据采集卡的资源,例如计数器。
当你设置一个模入应用时,首先使用的 VI总是 AI Config。 AI Config会产生一个 taskID
和 Error cluster(出错信息簇) 。所有别的模入 VI 接受这个 taskID 以识别操作的设备和通道,并且在操作完成后输出一个 taskID。因为 taskID 是一个输入并向另一个模入 VI 输出,所以该参数形成了采集 VI 之间的一个关联数据。
练习 6-3
目的:多通道波形的连续采集
现在我们使用 LabVIEW 提供的 DAQ 向导来搭建这个程序,操作步骤如下,
1.选 LabVIEW 进入画面选择 DAQ Solutions
2.进入 Welcome to the Solution Wizard 选
null Program the input scaling and conversion myself
3.进入 Solution Wizard –Step 2 to 3 选
null Custom DAQ Applications
4.进入 Solution Wizard –Step 3 to 3 选
null Analog Input
5.进入 Analog Input Functionality 选
在 Step 1 中选择0、1两个通道
在 Step 2 中选择 Scan multiple sample from each channel continuously
点击 OK 按钮
6.又回到 Solution Wizard –Step 3 to 3,显示选中的各种配置,点击[ Open Solution]按
钮,可以看到形成的程序。
上面的面板和框图略做了简化,删去了有关错误信息处理的一个模块。在这个程序中有几个问题值得注意
1.在 AI Config 中设置 interchannel delay 为 –1,使用间隔扫描方式,避免了通道延迟。
2.在这个简化了的框图上我们可以更加清晰地看出中级模入的处理框图,大致如下,
图 6-16 连续采集程序模型
无疑,这个流程更加合理,它把采集的初始化与结束处理放在了循环之外。
1
device (1)
STOP
5.0
-5.0
-4.0
-2.0
0.0
2.0
4.0
3599934999 35200 35400 35600 35800
transposed waveform chart
10000.00
scan rate
(1000 scans/sec)
4000
buffer size
(4000 scans)
2000
scans to read
at a time (1000)
2
scan backlog
hardware settings
-1.00
interchannel delay
in secs ( -1,hw default)
0.00
high li
0.00
low lim
0
input limits
0:1
0
channels (0)
channels (0)
input limits
interchannel delay
in secs ( -1,hw default)
0
buffer size
(4000 scans)
scan rate
(1000 scans/sec)
transposed waveform chart
scans to read
at a time (1000)
scan backlog
Read & chart data until an error
occurs,or the stop button pressed.
0
continuous
acquisition
device (1)
3,Buffer 的设置和使用,连续采集时通常需要 Buffer。 面板上有3个与 Buffer 有关的对象。
其一是 Buffer Size(单位,scan 的个数 ),这是它的大小,其二是 Scans to Read at a time,
即每一次从 Buffer 中读走的 scan 的个数,其三是 scan backlog,这里显示在 Buffer 中积压的 scan 个数。这个数的大小取决于系统的运行速度。只要这里显示一个大于 Buffer
Size 的数,系统将出错,中断运行。
这里使用的是一种称为循环 Buffer 机制。其原理如下:在往缓冲区中放数据的
同时可以读取缓冲区中已放的数据,当缓冲区满时,从缓冲区开始处重新存放新的数
据,只要放数据和取数据的速度配合好,就可以实现用一块有限的存储区,来进行连
续的数据传送。使用循环缓冲区,可以在采集设备在后台连续进行采集的同时,
LabVIEW 在两次读取缓冲区数据的时间间隔里对数据进行处理。循环缓冲区 存取数据
说明如图 6-17 所示。
图 6-17 循环缓冲区存取数据说明
程序读取数据的速度要不慢于采集设备往缓冲区中放数据的速度,才能保证连续运行时,缓冲区中的数据不会溢出,不会丢数据。如果程序取数据的速度快于放数据的速度,LabVIEW 会等待数据放好后再读取。如果程序读取数据的速度慢于放数据的速度,
LabVIEW 发送一个错误信息,告诉用户有一些数据可能被覆盖并丢失。可以通过调整三个参数来解决这个问题,input buffer size,scan rate 和 number of scans to read at a time。
增大 input buffer size 可以延长填满缓冲区的时间,但是这不能根本上解决连续采集过程中数据被覆盖的问题,要根本解决这个问题,需要减小 scan rate 或者增大 number of scans
to read at a time。 number of scans to read at a time 一般设置为一个小于缓冲区大小的值,
缓冲区大小一般设置为 scan rate 的两倍。具体的设置需要通过测试整个采集程序运行的情况来确定。 可以通过查看输出端的 scan backlog 的大小判断缓冲中数据会不会被覆盖,
scan backlog 被定义为从采集缓存中采集到而不是读到的扫描个数,是一个衡量系统是否跟得上连续采集数据的一个量度,如果 scan backlog 的数值一直在上升则表明从缓存中读数据的速度不够快并且最终会丢失数据,如果丢失数据,AI Read VI 将会给出错误提示。
练习 6-3 结束
6.3 模出( Analog Output)
6.3.1 基本参数与术语
多功能的 DAQ 卡用数模转换器( D/A)将数字信号转换成模拟信号,D/A 的有关参数有范围( Range),分辨率( Resolution),单调性( Monotonicity),线性误差 (Linearity Error)、
建立时间 (Settling Time)、转换速率( Slew Rate),精度( Accuracy)等。下面对部分参数做一些解释。
建立时间 (Settling Time),是指变化量为满刻度时,达到终值 1/2LSB 时所需的时间。这个参数反映 D/A 的 D/A 转换从一个稳态值到另一个稳态值的过渡过程的长短。建立时间一般为几十纳秒至几微秒。
转换速率 (Slew Rate),是指 D/A 输出能达到的最大变化速率,即电平变化除以转换所用时间,通常指电压满范围内的转换速率。
精度( Accuracy),分为绝对精度和相对精度。绝对精度是指输入某已知数字量时其理论输出模拟值和实际所测得的输出值之差,该误差一般应低于 1/2LSB。相对精度是绝对精度相对于额定满度输出值的比值,可用偏差多少 LSB 或者相对满度的百分比表示。 D/A 的分辨率越高,数字电平的个数就越多,精度越高。 D/A 范围增大,精度就会下降。
由建立时间和转换速度可以得到 D/A 转换输出信号电平的快慢。一个有着更小的建立时间和更高的转换速率的 D/A 可以产生更高的输出信号频率,因为它达到新的电平所需的时间更少。
图 6-18 Settling Time 和 Slew Rate
6.3.2 简易模出 (Easy Analog Output)
与简易模入类似,这里也提供了4个模块,分别对应于单(多)通道输出波形或电压数据。下面我们通过练习来讨论
练习 6-4
目的:产生一个模出电平
1
device
3.00
value to generate
10.0
0.0
2.0
4.0 6.0
8.0
data output meter
0
channel
做面板及框图如上。运行该程序,可以看到表的输出将指示3。这个指示并非模出,为了看到模出,可以使用一块数字万用表直接测量 DAC0 OUT。你会发现万用表的指示一直维持在3 V,尽管程序早已执行完了。
练习 6-4 结束
练习 6-5
目的:产生一个模出波形
做面板及框图如上。框图中我们首先产生一个正弦波形(其初相位可控),然后将它送给模出,同时连接到一个 Graph 显示。运行该程序,可以使用一块数字万用表的直流电压档直接测量 DAC0 OUT。你会发现当初相位为0时,万用表的指示是0,当初相位为 90 度时,
万用表的指示是 1。这表明该程序输出的不是一个连续不断的波形,仅仅是一个或若干个整周期的波形。模出模块在结束操作后并没有清0复位,一直维持在最后一刻的电平上。如果希望产生一个连续不断的波形,需要使用下面的较复杂的中级函数模块。
练习 6-5 结束
6.3.3 中级模出( Analog Output)
AO Config 对指定的通道设置模出操作,包括硬件、计算机内 buffer 的分配。常用的端子有,
null Device——采集卡的设备号。
null Channel——指定模出通道号的串数组。
null Limit settings——指定输出信号的范围。
null taskID——用于所有后来的模出 VI 以规定操作的设备和通道。
AO Write 以电压数据的方式写数据到模出数据缓冲区。它是一个2维数组,其中每一列数据对应于通道列表中的一个通道。注意:通常其他函数为其准备的波形数据是一个1维数组,且数据分布在一行中,这里需要将其“虚扩”为二维数组,并做一次转置。
AO Start 启动带缓冲的模出操作。 Update rate(scan/sec)是每秒发生的更新数的个数。
如果你将0写入 Number of buffer iteerations 端子,则卡将连续输出给缓冲,直到运行
AO Clear 功能。
AO Wait 在返回之前一直等待直到波形发生任务完成。它的电压数据输出是由通道列表中的每个通道读出的电压数据。使用这个 VI 仅与 AO Config 有关联,不需要 AO Start 和
AO Read。
AO Clear——清除模出操作、计算机中分配的缓冲、释放所有数据采集卡的资源,例如计数器。
当你设置一个模出应用时,首先使用的 VI 总是 AO Config。 AO Config 会产生一个 taskID
和 Error cluster(出错信息簇) 。所有别的模出 VI 接受这个 taskID 以识别操作的设备和通道,并且在操作完成后输出一个 taskID。该参数形成了采集 VI 之间的一个关联数据。
练习 6-6
目的:产生一个连续的正弦信号(1)
做面板及框图如下。
2
update rate (1000 updates/sec)
0
Y
Waveform Graph
frequency
buffer size (1000 updates)
status
stop
上面的框图中需要说明以下几点,
由于 AO Write 要求输入数据的要求(见上文),这里正弦波发生器的输出是一个
waveform 数据类型,首先将其中的 Y 数据提出,然后将它扩充为一个二维数组,再经转置后才可连接到 AO Write 。
在 AO Config 中主要是设置了 Buffer,这对于连续输出是必须的,其它都选默认值。
Buffer 的大小有时需要经过调试,过大或过小都可能导致不能正常工作。
练习 6-6 结束
练习 6-7
目的:产生一个连续的正弦信号(2)
下面我们使用 Analog Output Utilities 下提供的连续模出的现成模块再做一个连续的正弦信号发生器。面板与框图如下所示,
该例子中开关是控制 AO C-GEN 内部的 AO Clear 模块。当其状态为 T 时,运行程序将释放计算机及采集卡资源,无信号输出。
在程序框图上点击 AO C-GEN 图标,可以看到其内部结构。
练习 6-7 结束
sampling info
frequency
clear generation
5.00
Y
dt
t0
第七章 信号处理与分析
7.1 概述
数字信号在我们周围无所不在。因为数字信号具有高保真、低噪声和便于信号处理的优点,所以得到了广泛的应用,例如电话公司使用数字信号传输语音,广播、电视和高保真音响系统也都在逐渐数字化。太空中的卫星将测得数据以数字信号的形式发送到地面接收站。
对遥远星球和外部空间拍摄的照片也是采用数字方法处理,去除干扰,获得有用的信息。经济数据、人口普查结果、股票市场价格都可以采用数字信号的形式获得。因为数字信号处理具有这么多优点,在用计算机对模拟信号进行处理之前也常把它们先转换成数字信号。本章将介绍数字信号处理的基本知识,并介绍由上百个数字信号处理和分析的 VI 构成的
LabVIEW 分析软件库。
目前,对于实时分析系统,高速浮点运算和数字信号处理已经变得越来越重要。这些系统被广泛应用到生物医学数据处理、语音识别、数字音频和图像处理等各种领域。数据分析的重要性在于,无法从刚刚采集的数据立刻得到有用的信息,如下图所示。必须消除噪音干扰、纠正设备故障而破坏的数据,或者补偿环境影响,如温度和湿度等。
通过分析和处理数字信号,可以从噪声中分离出有用的信息,并用比原始数据更全面的表格显示这些信息。下图显示的是经过处理的数据曲线。
用于测量的虚拟仪器 (VI)
用于测量的虚拟仪器 (VI)执行的典型的测量任务有,
null 计算信号中存在的总的谐波失真。
null 决定系统的脉冲响应或传递函数。
null 估计系统的动态响应参数,例如上升时间、超调量等等。
null 计算信号的幅频特性和相频特性。
null 估计信号中含有的交流成分和直流成分。
在过去,这些计算工作需要通过特定的实验工作台来进行,而用于测量的虚拟仪器可以使这些测量工作通过 LabVIEW 程序语言在台式机上进行。这些用于测量的虚拟仪器是建立在数据采集和数字信号处理的基础之上,有如下的特性,
null 输入的时域信号被假定为实数值。
null 输出数据中包含大小、相位,并且用合适的单位进行了刻度,可用来直接进行图形的绘制。
null 计算出来的频谱是单边的( single_sided),范围从直流分量到 Nyquist 频率 (二分之一取样频率 )。 (即没有负频率出现)
null 需要时可以使用窗函数,窗是经过刻度地,因此每个窗提供相同的频谱幅度峰值,可以精确地限制信号的幅值。
一般情况下,可以将数据采集 VI 的输出直接连接到测量 VI 的输入端。测量 VI 的输出又可以连接到绘图 VI 以得到可视的显示。
有些测量 VI 用来进行时域到频域的转换,例如计算幅频特性和相频特性、功率谱、网路的传递函数等等。另一些测量 VI 可以刻度时域窗和对功率和频率进行估算。
本章我们将介绍测量 VI 中常用的一些数字信号处理函数。
LabVIEW 的流程图编程方法和分析 VI 库的扩展工具箱使得分析软件的开发变得更加简单。 LabVIEW 分析 VI 通过一些可以互相连接的 VI,提供了最先进的数据分析技术。你不必像在普通编程语言中那样关心分析步骤的具体细节,而可以集中注意力解决信号处理与分析方面的问题。 LabVIEW 6i 版本中,有两个子模板涉及信号处理和数学,分别是 Analyze
子模板和 Methematics 子模板。这里主要涉及前者。
进入 Functions 模板 Analyze,Signal Processing 子模板。
其中共有 6 个分析 VI 库。其中包括,
①,Signal Generation(信号发生),用于产生数字特性曲线和波形。
②,Time Domain(时域分析),用于进行频域转换、频域分析等。
③,Frequency Domain(频域分析),
④,Measurement(测量函数),用于执行各种测量功能,例如单边 FFT,频谱、比例加窗以及泄漏频谱、能量的估算。
⑤,Digital Filters(数字滤波器),用于执行 IIR,FIR 和非线性滤波功能。
⑥,Windowing(窗函数),用于对数据加窗。
在后面几节中,你将学习如何使用分析库中的 VI 创建函数发生器和简单实用的频谱分析仪,如何使用数字滤波器,窗函数的作用以及不同类型窗函数的优点,怎样执行简单的曲线拟合功能,以及其他一些内容。可以在 labview\examples\analysis 目录中找到一些演示程序。
7.2 信号的产生
本节将介绍怎样产生标准频率的信号,以及怎样创建模拟函数发生器。参考例子见
examples\analysis\sigxmpl.llb。
你还将学习怎样使用分析库中的信号发生 VI 产生各种类型的信号。信号产生的应用主要有,
null 当无法获得实际信号时,(例如没有 DAQ 板卡来获得实际信号或者受限制无法访问实际信号),信号发生功能可以产生模拟信号测试程序。
null 产生用于 D/A 转换的信号
在 LabVIEW 6i 中提供了波形函数,为制作函数发生器提供了方便。以
Waveform>>Waveform Generation 中的基本函数发生器( Basic Function Generator.vi)为例,
其图标如下,
其功能是建立一个输出波形,该波形类型有:正弦波、三角波、锯齿波和方波。这个 VI 会记住产生的前一波形的时间标志并且由此点开始使时间标志连续增长。 它的输入参数有波形类型、样本数、起始相位、波形频率(单位,Hz)
参数说明,
offset,波形的直流偏移量,缺省值为 0.0。数据类型 DBL
reset signal,将波形相位重置为相位控制值且将时间标志置为 0。缺省值为 FALSE,
signal type,产生的波形的类型,缺省值为正弦波。
frequency,波形频率(单位 Hz),缺省值为 10。
amplitude,波形幅值,也称为峰值电压,缺省值为 1.0。
phase,波形的初始相位(单位 度)缺省值为 0.0,
error in,在该 VI 运行之前描述错误环境。缺省值为 no error,如果一个错误已经发生,该
VI 在 error out 端返回错误代码。该 VI 仅在无错误时正常运行。 错误簇包含如下参数。
status,缺省值为 FALSE,发生错误时变为 TRUE。
code,错误代码,缺省值为 0。
source,在大多数情况下是产生错误的 VI 或函数的名称,缺省值为一个空串。
sampling info,一个包括采样信息的簇。共有 Fs 和 #s 两个参数。
Fs,采样率,单位是样本数 /秒,缺省值为 1000。
#s,波形的样本数,缺省值为 1000。
duty cycle (%),占空比,对方波信号是反映一个周期内高低电平所占的比例,缺省值为 50%。
signal out:信号输出端
phase out,波形的相位,单位:度。
error out,错误信息。如果 error in 指示一个错误,error out 包含同样的错误信息。否则,
它描述该 VI 引起的错误状态。
使用该 VI 制作的函数发生器如下,由框图可以看出,其中没有附加任何其他部件。
7.3 标准频率
在模拟状态下,信号频率用 Hz 或者每秒周期数为单位。但是在数字系统中,通常使用数字频率,它是模拟频率和采样频率的比值,表达式如下,
数字频率=模拟频率 /采样频率
这种数字频率被称为标准频率,单位是周期数 /采样点。
z 有些信号发生 VI 使用输入频率控制量 f,它的单位和标准频率的单位相同:周期数 /
每个采样点,范围从 0 到 1,对应实际频率中的 0 到采样频率 fs 的全部频率。它还以 1.0 为周期,从而令标准频率中的 1.1 与 0.1 相等。 例如某个信号的采样频率是奈奎斯特频率 ( fs/2),
就表示每半个周期采样一次(也就是每个周期采样两次) 。与之对应的标准频率是 1/2 周期数 /采样点,也就是 0.5 周期数 /采样点。标准频率的倒数 1/f 表示一个周期内采样的次数。
如果你所使用的 VI 需要以标准频率作为输入,就必须把频率单位转换为标准单位:周期数 /采样点。
7.4 数字信号处理
7.4.1 FFT 变换
信号的时域显示(采样点的幅值)可以通过离散傅立叶变换( DFT)的方法转换为频域显示。为了快速计算 DFT,通常采用一种快速傅立叶变换 (FFT)的方法。当信号的采样点数是 2 的幂时,就可以采用这种方法。
FFT 的输出都是双边的,它同时显示了正负频率的信息。通过只使用一半 FFT 输出采样点转换成单边 FFT。 FFT 的采样点之间的频率间隔是 fs/N,这里 fs 是采样频率。
Analyze 库中有两个可以进行 FFT 的 VI,分别是 Real FFT VI 和 Complex FFT VI。
这两个 VI 之间的区别在于,前者用于计算实数信号的 FFT,而后者用于计算复数信号的 FFT。它们的输出都是复数。
大多数实际采集的信号都是实数,因此对于多数应用都使用 Real FFT VI 。当然也可以通过设置信号的虚部为 0,使用 Complex FFT VI 。使用 Complex FFT VI 的一个实例是信号含有实部和虚部。这种信号通常出现在数据通信中,因为这时需要用复指数调制波形。
计算每个 FFT 显示的频率分量的能量的方法是对频率分量的幅值平方。高级分析库中
Power Spectrum VI 可以自动计算能量频谱。 Power Spectrum VI 的输出单位是 Vrms
2
。但是能量频谱不能提供任何相位信息。
FFT 和能量频谱可以用于测量静止或者动态信号的频率信息。 FFT 提供了信号在整个采样期间的平均频率信息。因此,FFT 主要用于固定信号的分析(即信号在采样期间的频率变化不大)或者只需要求取每个频率分量的平均能量。
2.流程图中的 Array Size 函数用来根据样本数转换 FFT 的输出,得到频率分量的正确幅值。
3.把该 VI 保存为 LabVIEW\Activity 目录中的 FFT_2sided.vi。
4.选择频率( Hz) =10,采样率 = 100,样本数 = 100。执行该 VI。注意这时的时域图和频谱图。因为采样率 =样本数 = 100,所以时域图中的正弦波的周期数与选择的频率相等,
即可以显示 10 个周期。 (如果把频率改成 5,那么就会显示 5 个周期)
Y
dt
t0
0
频谱时域信号样本数采样频率频率( HZ)
双边 FFT
5.检查频谱图可以看到有两个波峰,一个位于 10Hz,另一个位于 90Hz,90Hz 处的波峰实际上是 10Hz 处的波峰的负值。因为图形同时显示了正负频率,所以被称为双边 FFT。
6.先后令频率 =10,20( Hz),执行该 VI。注意每种情况下频谱图中波峰位置的移动。
观察频率等于 10 和 20 时的时域波形。注意哪种情况下的波形显示更好,并解释原因。
7.因为 fs = 100 Hz,所有只能采样频率低于 50Hz 的信号(奈奎斯特频率= fs/2) 。把频率修改为 48Hz,可以看到频谱图的波峰位于 ± 48 Hz。
8.把频率改为 52HZ,观察这时产生的图形与第 5 步产生的图形的区别。因为 52 大于奈奎斯特频率,所以混频偏差等于 |100 – 52| = 48 Hz。
9.把频率改成 30 和 70Hz,执行该 VI。观察这两种情况下图形是否相同,并解释原因。
单边 FFT
10.按照下图修改流程图。上面已经知道因为 FFT 含有正负频率的信息,所以可以 FFT
具有重复信息。现在这样修改之后只显示一半的 FFT 采样点(正频率部分) 。这样的方法叫做单边 FFT。单边 FFT 只显示正频部分。注意要把正频分量的幅值乘以 2 才能得到正确的幅值。但是,直流分量保持不变。 (若程序中考虑含直流分量的情况,应当增加一个分支或
case 结构。
2.00
2
Y
dt
t0
0
频谱时域信号序列样本数采样频率频率( HZ)
11.设置频率( Hz) = 30,采样率 = 100,样本数 = 100,运行该 VI。
12.保存该 VI 为 LabVIEW\Activity 目录下的 FFT_1sided.vi。
13.把频率改为 70Hz,执行该 VI,观察这时产生的图形与第 9 步产生的图形的区别。
练习 6-1 结束。
6.4.2 窗函数
计算机只能处理有限长度的信号,原信号 x(t)要以 T(采样时间或采样长度 )截断,即有限化。有限化也称为加“矩形窗”或“不加窗” 。矩形窗将信号突然截断,这在频域造成很宽的附加频率成分,这些附加频率成分在原信号 x(t)中其实是不存在的。一般将这一问题称为有限化带来的泄露问题。泄露使得原来集中在 f
0
上的能量分散到全部频率轴上。泄露带来许多问题:如①使频率曲线产生许多“皱纹” ( Ripple),较大的皱纹可能与小的共振峰值混淆;②如信号为两幅值一大一小频率很接近的正弦波合成,幅值较小的一个信号可能被淹没。③ f
0
附近曲线过于平缓,无法准确确定 f
0
的值。
为了减少泄露,人们尝试用过渡较为缓慢的、非矩形的窗口函数。常用的窗函数如下表所示。
窗 定 义 应 用
矩形窗(无窗)
W[n]=1.0
区分频域和振幅接近的信号瞬时信号宽度小于窗
指数形窗
W[n]=exp[n*lnf/N-1]
f=终值
瞬时信号宽度大于窗
海宁窗 W[n]=0.5cos(2nπ /N) 瞬时信号宽度大于窗普通目的的应用
海明窗 W[n]=0.54-0.46cos(2nπ /N) 声音处理
平顶窗
W[n]=0.2810639-0.5208972cos(
2nπ /N)
+0.1980399cos(2nπ /N)
分析无精确参照物且要求精确测量的信号
Kaiser-Bessel 窗 W[n]=Io (β ) 区分频率接近而形状不同的信号三角形窗 W[n]=1-|( 2n-N) /N| 无特殊应用
在实际应用中如何选择窗函数一般说来是要仔细分析信号的特征以及最终你希望达到的目的,并经反复调试。窗函数有利有弊,使用不当还会带来坏处。使用窗函数的原因很多,
例如,
null 规定测量的持续时间。
null 减少频谱泄漏。
null 从频率接近的信号中分离出幅值不同的信号。
下面的例子(详见 LabVIEW 6i 中的 Search Examples > Fundamentals Examples
>Analysis Examples > Signal Processing > Windows Examples > Window Comparison)是从频率接近的信号中分离出幅值不同的信号,正弦波1与正弦波2频率较接近,但幅值相差
1000 倍,相加后产生的信号变换到频域,如果在 FFT 之前不加窗,则 频域特性中幅值较小的信号被淹没。加 Hanning 窗后两个频率成分都被检出。
1.0
-1.0
-0.5
0.0
0.5
990 10 20 30 40 50 60 70 80 90
Time Domain
0
-140
-120
-100
-80
-60
-40
-20
2550 50 100 150 200
None
Hanning
频域特性不同类型窗口函数在频域的效果。不使用窗口函数时,幅值较小的正弦波 1被淹没。
使用 Hanning窗口函数后 (Window 2),幅值较小的正弦波 1被发现。
Stop
100.0
0.0
20.0
40.0 60.0
80.0
73.92频率 1
正弦波形 1 正弦波形 2
正弦波形 1 +正弦波形 2
0.001
幅值 1
1.000
幅值 2
100.0
0.0
20.0
40.0 60.0
80.0
59.24
频率 2
dB
None
Window 1
Hanning
Window 2
7.4.3 谐波失真与频谱分析
当一个含有单一频率 (比如 f
1
)的信号 x(t)通过一个非线性系统时,系统的输出不仅包含输入信号的频率( f
1
),而且包含谐波分量( f
2
=2f
1
,f
3
=3f
1
,f
4
=4f
1
等等),谐波的数量以及它们对应的幅值大小取决于系统的非线性程度。电网中的谐波是一个值得关注的问题。
下面的一个非线性系统的例子是输出 y(t)是输入 x(t)的立方。假如输入信号,
)cos()( wttx =
则输出,
)]3cos()[cos(25.0)cos(5.0)(
3
wtwtwttx ++=
因此,输出不仅含有基波频率 w,而且还有三次谐波的频率 3w。
谐波失真的总量
为了决定一个系统引入非线性失真的大小,需要得到系统引入的谐波分量的幅值和基波的幅值的关系。谐波失真是谐波分量的幅值和基波幅值的相对量。假如基波的幅值是 A
1
,
而二次谐波的幅值是 A
2
,三次谐波的幅值是 A
3
,四次谐波的幅值是 A
4
。 。 。 。 。 。 N 次谐波的幅值是 A
N
,总的谐波失真( THD)为,
1
22
3
2
2
...
A
AAA
N
THD
++
=
用百分数表示的谐波失真( %THD)为,
1
22
3
2
2
...*100
%
A
AAA
N
THD
++
=
LabVIEW 6i 提供的谐波分析器与以前的版本有一些变化,下面先介绍它
该 VI 对输入信号进行完整的谐波分析,包括测定基波和谐波,返回基波频率和所有的谐波幅度电平,以及总的谐波失真度( THD) 。其部分参数含义如下,
stop search at Nyquist:如果设置为 TRUE (缺省值 T),则只包含低于 Nyquist 频率(采样频率的一半)的谐波。如果设置为 FALSE,该 VI 将继续搜索 Nyquist 范围之外的频率。
signal in,输入信号。
export signals,选择输出到信号指示器的信号。有如下几种选择,
none——对快速计算;
input signal——定时将输入信号反映到输出端;
fundamental signal——在输出端反映基波;
residual signal——在输出端反映除基波之外的剩余信号;
harmonics only——在输出端反映谐波时域信号及其频谱。
highest harmonic,控制最高谐波成分,包括用于谐波分析的基波。例如,对于 3 次谐波分析,该控制将设置测量基波,2 次谐波和 3 次谐波。,
error in,在该 VI 运行之前描述错误环境。缺省值为 no error,如果一个错误发生,该 VI
在 error out 端返回错误代码。该 VI 仅在无错误时正常运行。 错误簇包含如下参数。
status,缺省值为 FALSE,发生错误时变为 TRUE。
code,错误代码,缺省值为 0。
source,在大多数情况下是产生错误的 VI 或函数的名称,缺省值为一个空串。
advanced search,控制频域搜索区域,中心频率及频带宽度。该功能用来确定信号的基波。
approx,fund,freq,(optional) ——用来搜索基波的中心频率的估算值。 如果设置缺省值为 -1.0,,则选择幅值最大的频率成分为基波。
search (+/- % of Fsampl.) ——用来搜索基波频率频带宽度,是采样率的百分比。
exported signals,包含输出的时域信号及其频谱供选择。
detected fundamental frequency,探测在频域搜索得到的基波。用 advanced search 设置频率搜索范围。所有谐波测量为基波的整数倍。
THD,总谐波失真度。它定义为谐波 RMS 之和与基波幅值之比。为了折算为百分数,需要乘以 100。
components level,测量谐波幅值的电平(单位 伏),是一个数组。该数组索引包括 0 (DC),
1 (基波 ),2 (2 次谐波 ),..,n (n 次谐波 ),直到最高谐波成分。
measurement info cluster,任何处理期间遭遇的预告
uncertainty 备用;
Warning,如果处理期间警告发生为 TRUE。
comments,当 Warning 为 TRUE 时的消息内容。
下面是一个谐波分析的例子。由通道 0 输入一个模拟信号,经 DAQ 后进行谐波分析,
先后分析了两个信号,首先是一个 761Hz 的正弦信号,第二个信号是一个 1000Hz 的。分析仅限于不高于 5 次的谐波。分析结果见两个前面板。对一个实际的正弦信号,谐波失真总量
( THD)与基波电平相比,可以忽略。对方波 THD 就较大了。
谐波分析应用的一个例子
6.3.1 数字滤波
模拟滤波器设计是电子设计中最重要的部分之一。 尽管很多参考书都提供了简单可靠的模拟滤波器示例,但是滤波器的设计通常还是需要专家来完成,因为这项工作需要较高深的数学知识和对系统与滤波器之间的关系有深入的了解。
现代的数字采样和信号处理技术已经可以取代模拟滤波器,
尤其在一些需要灵活性和编程能力的领域中,例如音频、通讯、
地球物理和医疗监控技术。
与模拟滤波器相比,数字滤波器具有下列优点,
null 可以用软件编程
null 稳定性高,可预测
null 不会因温度、湿度的影响产生误差,不需要精度组件
null 很高的性能价格比
在 LabVIEW 中可以用数字滤波器控制滤波器顺序、截止频率、脉冲个数和阻带衰减等参数。
本节所涉及到的数字滤波器都符合虚拟仪器的使用方法。 它们可以处理所有的设计问题、计算、内存管理,并在内部执行实际的数字滤波功能。 这样您无需成为一个数字滤波器或者数字滤波的专家就可以对数据进行处理。
采样理论指出,只要采样频率是信号最高频率的两倍以上就可以根据离散的、等分的样本还原一个时域连续的信号。假设对信号以△ t 为时间间隔进行采样,并且不丢失任何信息,参数 △
t 是采样间隔。
可以根据采样间隔计算出采样频率
根据上面的公式和采样理论可以知道,信号系统的最高频率可以表示为,
系统所能处理的最高频率是恩奎斯特频率。 这同样适用于数字滤波器。例如,如果采样间隔是 0.001 秒,那么采样频率是
系统所能处理的最高频率是
下面几种滤波操作都基于滤波器设计技术,
null 平滑窗口
null 无限冲激响应( IIR)或者递归数字滤波器
null 有限冲激响应( FIR)或者非递归数字滤波器
null 非线性滤波器
很多情况下通带的增益在均值附近稍微发生变化是容许的。
通带的这种变化被称为通带波动( passband ripple),也就是实际增益与理想增益之间的差值。在实际使用中阻带衰减
( stopband attenuation)也不可能无限接近 0,您必须指定一个符合需要的衰减值。通带波动和阻带衰减都使用分贝或者 dB
为单位,定义是,
其中 log10表示基值 10 的对数,而 Ai(f) and A0(f) 分别是频率在滤波前后的幅值。 例如,对于– 0.02 dB 的通带波动,表达式是,
这表明输入输出的幅值非常接近。
如果阻带衰减为– 60 dB,那么可以得到,
这表明输出幅值是输入幅值的 1/1000。
衰减值通常用不带负号的分贝为单位,但是默认为负值。
IIR 和 FIR 滤波器
另外一种滤波器分类方法是根据它们的冲激响应的类型。 滤波器对于输入的冲激信号( x[0] = 1 且对于所有 I<>0,x[i] =
0)的响应叫做滤波器的冲激响应( impulse response),如下图所示。冲激响应的傅立叶变换被称为滤波器的频率响应
( frequency response)。根据滤波器的频率响应可以求出滤波器在不同频率下的输出。换句话说,根据它可以求出滤波器在不同频率时的增益值。对于理想滤波器,通频带的增益应当为 1,
阻带的增益应当为 0。所以,通频带的所有频率都被输出,而阻带的所有频率都不被输出。
如果滤波器的冲激响应在一定时间之后衰减为 0,那么这个滤波器被称为有限冲激响应( FIR)滤波器。但是,如果冲激响应一直保持,那么这个滤波器被称为无限冲激响应滤波器 ( IIR) 。
冲激响应是否有限(即滤波器是 IIR 还是 FIR)取决于滤波器的输出的计算方法。
IIR 滤波器和 FIR 滤波器之间最基本的差别是,对于 IIR 滤波器,输出只取决于当前和以前的输入值,而对于 FIR 滤波器,
输出不仅取决于当前和以前的输入值,还取决于以前的输出值。
简单地说,FIR 滤波器需要使用递归算法。
IIR 滤波器的缺点是它的相位响应是非线形的。在不需要相位信息的情况下,例如简单的信号监控,那么 IIR 滤波器就符合需要。而对于那些需要线形相位响应的情况,应当使用 FIR 滤波器。但是,IIR 滤波器的递归性增大了它的设计与执行的难度。
因为滤波器的初始状态是 0(负指数是 0),所以在到达稳态之前会出现与滤波器阶数相对应的过渡过程。 对于低通和高通滤波器,过渡过程或者延迟的持续时间等于滤波器的阶数。
可以通过启动静止内存消除连续调用中的过渡过程,方法是将 VI 的 init/cont 控制对象设置为 TURE(连续滤波)。
对数字滤波器的详细讨论不是本书的内容,读者可参阅有关数字信号处理的书籍,下面我们具一个简单的例子说明在
LabVIEW 中如何使用数字滤波器。
练习 6-2 使用数字滤波器
目的:使用一个低通数字滤波器对实际采集的方波信号滤波。
1.创建前面板和流程图如下所示。
90.00
6
Filtered X
Lowpasswaveform
sample rate
number of samples
1
2.注意流程图。其中使用了一个数字滤波器模块( Functions 模板,Analyze) Signal
Processing) Filters 下的 Butterworth Filter.vi) 。先介绍一下这个 VI。
Butterworth 滤波器
filter type,按下列值指定滤波器类型
0,Lowpass 低通
1,Highpass 高通
2,Bandpass 带通
3,Bandstop 带阻
X,需要滤波的信号序列
sampling freq fs,产生 X 序列时的采样频率,必须大于 0。缺省值是 1.0。如果它小于等于 0 则输出序列 Filtered X 为空并返回一个错误。
high cutoff freq fh,高端截止频率。当滤波器类型为 0 (lowpass) 或 1 (highpass)时忽略该参数。
low cutoff freq fl:低 端截止频率。它必须满足 Nyquist 准则,即
0≦ f
i
<0.5f
s
如果该条件不满足则输出序列 Filtered X 为空并返回一个错误。 f
i
的缺省值是 0.125。
order,大于 0,缺省值是 2。
init/cont,内部状态的初始化控制。当其为 FALSE (default),初态为 0,当 init/cont 为
TRUE,滤波器初态为上一次调用该 VI 的最后状态。为了对一个大数据量的序列进行滤波,
可以将其分割为较小的块,设置这个状态为 FALSE 处理第一块数据,然后改设置为 TRUE
继续对对其余的数据块滤波。
Filtered X,滤波样本的输出数组。
3.在了解了这个滤波器的功能之后再来看上面的流程图。
这里 DAQ 部分将一个外部的 1KHz 的方波采集进来,采样频率是 100KHz,采到的方波一方面显示其波形,同时又送到滤波器的入口。滤波器类型设置为 Lowpass,其采样频率端直接连接到前面的采样频率控制端,因而也是 100KHz。另外,将采样频率除以 90 后作为低端截止频率,应该也是合理的,滤波器的阶数选为 6。这样的一个 VI 运行结果如前面板所示。
还需要指出的是原方波不以 X 轴对称,有直流分量,经这个低通滤波器后,直流分量还应当存在,曲线显示的确如此。
练习 6-2 结束。
6.3.2 曲线拟合
曲线拟合( curve fitting)技术用于从一组数据中提取曲线参数或者系数,以得到这组数据的函数表达式。
通常,对于每种指定类型的曲线拟合,如果没有特殊说明,都存在两种 VI 可以使用。
一种只返回数据,用于对数据的进一步操作,另一种不仅返回系数,还可以得到对应的拟合曲线和均方差( MSE) 。
LabVIEW 的分析软件库提供了多种线性和非线性的曲线拟合算法,例如线性拟合、指数拟合、通用多项式拟合、非线性 Levenberg-Marquardt 拟合等。
曲线拟合的实际应用很广泛。例如,
null 消除测量噪声
null 填充丢失的采样点(例如,如果一个或者多个采样点丢失或者记录不正确)
null 插值(对采样点之间的数据的估计;例如在采样点之间的时间差距不够大时)
null 外推 (对采样范围之外的数据进行估计,例如在需要在试验以后或者以后的数值时)
null 数据的差分(例如在需要知道采样点之间的偏移时,可以用一个多项式拟合离散数据,而得到的多项式可能不同)
null 数据的合成(例如在需要找出曲线下面的区域,同时又只知道这个曲线的若干个离散采样点的时候)
null 求解某个基于离散数据的对象的速度轨迹(一阶导数)和加速度轨迹(二阶导数)
下面是使用 LabVIEW 提供的算法得到的三种拟合的例子:线形拟合(左上),指数拟合(右上),多项式拟合(左下) 。
一般说来,采集得到的数据大都需要经过适当的处理,其中包括滤波、曲线拟合等。详细内容请参考有关资料。
第八章 数字 I/O
7.1 DI/O的基本知识
一般数据采集卡上都有 DI/O功能,用来实现数据采集的触发、控制及计数等功能。 DI/O
按 TTL逻辑电平设计,其逻辑低电平在 0到 0.7V之间,高电平在 3.4到 5.0V之间。
数采板上多路 (Line)数字 I/O 组成一组后被称为端口 ( Port) 。 一个端口由多少路数字 I/O
组成是依据其数采板而定的,在大多数情况下 4或 8路数字 I/O 组成一个端口。当读写端口时,你可以在同一时刻设置或获取多路 DI/O的状态。 MIO E 系列板卡有8路数字 I/O组成了一个端口,实际使用时这8路可以部分是输入,部分是输出。
数字量输入输出的应用分为以下两类:立即型(非锁存型)和定时型(锁存型) 。在立即型情况下,当你调用数字 I/O函数后立即更新或读取数字量某一路或端口的状态。在定时型情况下,你可以使用外部信号来控制数字量数据的传输。
LabVIEW 中关于 DI/O的 VI也分为低、中、高三个等级。
在以下几个不同的子模板中,
Data Acquisition? Digital I/O,顶层 — 用于较简单应用中的 Easy I/O VI。第二部分将讨论如何使用这些 VI。 LabVIEW基础教程中也将会详细讲述这些 VI。
Data Acquisition? Digital I/O,底层 — 是一些属于中级水平应用的 VI,主要用于需要时间或握手线方面的数字信号应用。这些 VI可用于单字节数据的传输。第三部分将详细讨论关于这方面数字量信号的操作。图 5-2 显示的是 Data Acquisition? Digital I/O 子模板。
Data Acquisition? Digital I/O? Advanced Digital I/O — 高级水平 DI/O VI 可用于作为创建其他数字 VI的基本模块。这些高级数字量 VI可用于立即型 DI/O和定时型 DI/O 。图 5-3显示的是 Data Acquisition? Digital I/O? Advanced Digital I/O 子模板。
图 5-2,Data Acquisition? DI/O 子模板
图 5-3,Data Acquisition? Digital I/O? Advanced Digital I/O 子模板
立即型 DI/O
立即型 DI/O 是最简单而且也是较经常使用的关于数字量方面的应用。它也叫非锁存型的 DI/O,所有带有 DI/O 接口的数采板都支持这种 DI/O 模式。在这种模式下,当 LabVIEW
调用函数后即可立即设置或获取某路 DI/O的状态。当某路 DI/O被设定为某一状态后,那么该路 DI/O 将一直保持这种状态直到其状态被重新设定为止。你可以通过软件改变某路 DI/O
是输入或是输出方式。下面将讨论 LabVIEW DAQ VI中的立即型 DI/O。
Easy I/O VI
使用 Easy I/O digital VI 你可以立刻输入或输出某一路(某一端口)的数字量。当你设置 DI/O VI iteration端为缺省参数时,每当你调用一次 DI/O 函数时系统将会按需要自动设置一次数采板。当你在一个循环中重复调用某个 DI/O 函数时,为了避免系统重复设置数采板,你可以设置 DI/O VI iteration 端为正数。这些 VI 可用于所有带有数字量输入输出的
NI数采板。
Write to Digital Line 设置某一端口中某一路 DI/O为逻辑高或者逻辑低状态 Device 是数采板的设备号( device number) ; Port number 是该路 DI/O 所在的端口号; Line 准备要写的该路 DI/O 的通道号; Line state 是指准备要写的该路 DI/O 的状态:高 (true) 或低
(false)。
图 5-4,Write to Digital Line
Read from Digital Line 读取某路 DI/O 的状态。 Device 是数采板的设备号( device
number) ; Port number 是该路 DI/O 所在的端口号; Line 准备要读取的该路 DI/O 的通道号; Line state 返回要读取的该路 DI/O 的状态:高 (true) 或低 (false)。
图 5-5,Read From Digital Line
Write to Digital Port 向某一指定的端口写一数字量,从而同时设定某一端口所有路
DI/O通道的状态。 Device 是数采板的设备号( device number) ; Port number 是准备要写的端口号; Pattern 是该端口要写的二进制或等同的十进制数字量。
图 5-6,Write to Digital Port
Read from Digital Port 读取某一指定端口所有路的 DI/O 通道的状态。 Device 是数采板的设备号( device number) ; Port number 是准备要读取的端口号; Pattern 是返回从该端口读取的数字量(十进制形式) 。
图 5-7,Read From Digital Port
如果在调用 Easy I/O digital VI 时发生错误,系统将会弹出一对话框显示出错代码,这时你可以终止或继续执行 VI。
注意,当你只调用一个 Easy I/O digital VI实例读或写某个通道或端口时,程序是不会出错的。
但是当再次调用函数时会通过改变移位寄存器的状态来重新改变 DI/O的设置,故你不能调用多个 VI实例来控制多个端口。 在这种情况下你可以通过使用下面将讨论的高级 VI来达到该目的。
高级 VI ( Advanced Vis)
使用高级 DI/O VI 也可以执行立即型 DI/O。 (实际上,Easy I/O VI 是由多个高级 VI所组成的) 。使用高级 VI你可以更高效的执行数字 I/O的读写工作,因为当你调用高级 VI 时,
它不会象使用 Easy I/O VI 那样每次运行时都需要去改变数采板的设置。高级 VI允许你使用通道屏蔽技术更新某一端口中数个 DI/O通道,而无须更新整个端口。根据高级 VI提供的错误信息你可以用来开发出自己错误处理程序。这些高级 VI 可用于所有带有数字量输入输出的 NI 数采板。
DIO Port Config 设置某个端口为写或读状态。 Device 和 port number设置板卡的设备号与端口号; Line direction map 设置端口为输入或输出状态;除了 TIO-10 与 MIO E 系列板卡外,其余板卡同一端口中所有各路 DI/O必须是同向的,即:同是输入或者同是输出。 task
ID out 的输出将用于下一 VI函数做为创建了一任务的唯一标识。
图 5-8,DIO Port Config V
DIO Port Write 根据已创建任务的标识 taskID立即更新端口的 DI/O通道状态。 pattern 输入的是一十进制数,当其换算为二进制时代表的是要更新的各路 DI/O通道的状态。举个例子来说:若设 pattern为 1(二进制 0001)那么将仅只设通道 0为高电位,若设 pattern为 15(二进制 1111)那将设通道 0,1,2,3为高电位。
图 5-9,DIO Port Write VI
使用 line mask 输入,你可以仅只改变你指定的 D /IO通道状态。 line mask 输入的是一十进制数字,该数字的值决定了那一个 DI/O通道的状态被更新。举个例子来说:若 line mask设为 1(二进制 0001)那么只有通道 0被更新,若 line mask设为 15(二进制 1111)那么通道 0,1,
2,3状态将被更新。未被包含在 line mask中的通道其状态将不会被改变。图 5-10 显示的两个例子就是使用 line mask来控制端口中那路 DI/O通道状态会被更新。你可以使用 Scale By
Power of 2 函数来选择单路通道或输入一十进制数直接选择多路通道。 在图 5-10a中,pattern
值设为 8(二进制 1000)时,通道 3将会被更新。在图 5-10b中,pattern值设为 6(二进制 0110)
时,通道 1,2将会被更新。假如你已设定该端口为输入状态,那么 error out 将会返回一个错误代码。
图 5-10,利用通道屏蔽技术来更新一个或多个通道的状态
DIO Port Read 根据已创建任务的标识 taskID来获得端口的 DI/O通道状态。 pattern 返回的是一十进制数,当其换算为二进制时代表的是各路 DI/O通道的状态。使用通道屏蔽技术你可以返回指定的通道状态,未被包含在 line mask中的通道其状态将在 pattern的返回值中被设为逻辑低(也就是 0) 。
图 5-11,DIO Port Read VI
立即型 DI/O 的应用
立即型 DI/O主要应用于:控制或监测继电器,作为计数器 Gate口的输入或者用于其他
TTL设备。例如可用立即型 DI/O控制 National Instruments SC-2062,SCXI-1160和 SCXI-1161继电器开关。
例 1—监测开关状态
本例演示如何使用 Easy I/O VI Read from Digital Line 来监测一外部开关的状态,关闭该开关后即初始化 LabVIEW测试程序。其硬件配置如图 5-12所示。
图 5-12,使用 DI/O监测开关的状态
在如图 5-13所示的程序框图中,Read from Digital Line连续不停的读取端口 0的第 0路通道的状态直到该通道状态为 TTL逻辑低(当开关关闭时),该 VI退出 While循环,然后运行下一测试子 VI。 Read from Digital Line设置端口为输入状态。
图 5-13,监测开关状态程序框图
例 2—继电器控制阀门
假如你想通过调节阀门来控制流入某个罐子中水的流量:当罐中液位低于某个位置时,
你想要打开阀门让水流入;当罐中液位高于某个位置时,你想要关闭阀门。通常情况下阀门是关闭的,所以你必须通过提供外部电力(如,120VAC)来打开阀门。图 5-14显示了如何使用 SCXI-1161继电器模块来控制这样一个系统。 SCXI-1161有 8个继电器(图 5-14仅显示了一个),每个继电器有一 COM位置,一 NC位置和一 NO位置。当通电完成后或处于歇息状态时,SCXI-1161即从 COM位置连接到 NC位置。
图 5-14,SCXI-1161控制阀门
在本例中,数采板上的某路数字量 I/O被设为输出模式后与继电器 0相连。 当向该路 DI/O
写 1时,与之相连的继电器会切换到 NO位置即连通电路从而打开阀门。下面图 5-15所示的
LabVIEW程序框图就是用高级 DI/O VI来控制该系统的。首先把 SCXI-1161模块的端口 0设为输出状态;用 Scale By Power Of 2函数创建一通道屏蔽仅控制通道 0; Get Tank Level 子 VI
返回罐子的液位。当液位低于设定的最低液位( LowLevel)时,程序即会向控制继电器的
DI/O通道写入 1从而打开阀门让水流入。与之相似,当罐子的液位高于设定的最高液位
( HighLevel)时,程序即会向控制继电器的 DI/O通道写入 0从而关闭阀门停止水的流入。
图 5-15,阀门控制的程序框图
继电器接触保护
我们经常连接电动机,阀门,螺线管以及白炽灯这些具有感应性质的负载到继电器上,
当继电器切换状态时就会产生巨大的反方向感生电动势。 因为这些感应负载存储了大量的能量,所以常常在这种情况下会毁坏继电器或者缩短其寿命。最好的方法就是使用一接触保护电路来限制在这种情况附加的感生电动势。你可以设置保护电路直接通过负载(在小型直流情况应用时,你可以把保护电路直接安装通过继电器接触段) 。假如你直接使用继电器,开启计算机时数采板会设置 DI/O 线的输入为高阻抗,你需要在 DI/O线上连接一电阻并在设置
DI/O为输出模式前将其设为一已知的状态。
练习 5-1
目标:使用一路 DI/O 完成一立即型数字量输出
建立一 VI可通过前面板的开关可控制试验盒上边 PA组的 LED灯的状态。当你开启开关时 LED灯亮,关闭开关时 LED灯灭。请使用 Data Acquisition? Digital I/O? Advanced Digital
I/O 模板中的 DIO Port Config 与 DIO Port Write VI(请不要改变该端口其他各路 DI/O的状态) 。你可以使用 Switch LED VI作为开始。
下图显示了试验盒上边 PA组的 LED灯与 DAQ板端口 0第 0路 DI/O的连接。
提示:确保 DIO Port Config VI 的 line direction map 的输入端是 -1,从而设置端口为输出模式。请记住 DAQ信号附件使用的是负逻辑:当你写假(逻辑低)时 LED则亮。且请使用通道屏蔽技术来更新 0路 DI/O。
练习 5-1 结束
练习 5-2
目标:在数字端口上执行立即型数字量输出
写一个 VI可随机产生一个 1到 4的整数,通过 DAQ信号附件端口 0上的 LED灯的状态来指示产生的是那一个随机数。假如是 1,则左边的 LED会亮而其他的灯全灭;假如是 2则最左边的第二个灯会亮,依次类推。使用 Data Acquisition? Digital I/O? Advanced Digital I/O模板中的 DIO Port Config 和 DIO Port Write VI。请使用 Digital Random Number VI开始。
练习 5-2结束
定时型DI/O
定时型 DI/O也叫做锁存型 I/O是第二种类型的数字量通信,它用来使用外部信号控制或作为握手信号的数据传输。 握手信号确保了在你初始化操作之前数采板或仪器已准备好了传输数据。
表 5-2显示的是数采板能有的锁存型 DI/O端口的数目。对于某些数采板,具备锁存功能的端口数目小于实际数采板上端口的总数目,这是因为这些数采板使用的是 Intel8255A
PPI芯片来控制数字线的。每个芯片是由 3个 8位的端口组成,当芯片上一个或多个端口设置为锁存型 DI/O时,这些端口中的某个端口上的几路 DI/O是保留用来作为控制握手信号的。
所以一个芯片上最多有两个端口被用做锁存型数字端口。
表 5-2,DAQ 板上能有的锁存型 DI/O 端口的数目
DI/O-32 型数采板有 4个 8路 DI/O端口。所有这些端口都可用做锁存型 DI/O。另外,这种类型数采板有另一定时型 DI/O功能即信号产生,是用一时钟产生握手信号来初始化数据传输。
这就意味着你可以以一定的频率输出或接受数字量数据。 这种方法在你的仪器或外部硬件不支持握手信号而你又想定时数据传输时是非常有用的。
定时型 DI/O VI
下面是使用握手线时传输数字量数据的高级 VI,
Digital Group Config 设置使用的 device 和 端口。 你设置 port list 组成了一组端口。 task
ID out 用来作为识别任务的标号。 group 输入是指已有一组端口,那么新设置将会替代已有的的设置。 group direction 输入端指定了组中的端口的方向。当该组支持握手线时
handshaking返回值为 1,否则为 0。
Figure 5-16,Digital Group Config VI
Digital Single Write 根据 task ID 任务标识执行数字量的输出。 opcode设定指定传输是否使用握手线。 Pattern list是一准备被输出的一维数组。 time limit设置决定传输时所分配的最大的时间。假如数据传输未在一定的时间内完成,函数将返回一个警告信息。 patterns written
输出将返回更新组( Group)后的组数。假如组中包含两个端口且 pattern list有 5个待输出的信号元素(即 2.5个组信号),那么仅只有前四个信号元素被输出且 patterns written的返回值为 2。
Figure 5-17,Digital Single Write VI
Digital Single Read 根据 task ID 任务标识执行组内端口的数字量读取。 Opcode输入端确定数据传输是否使用握手线。 Number to read确定是那一组输入被执行。 time limit设置决定传输时所分配的最大的时间。 假如数据传输未在一定的时间内完成,函数将返回一个警告信息。
Pattern list返回的是读取回的一维数组。 patterns read输出将返回读取组 ( Group) 后的组数。
Figure 5-18,Digital Single Read VI
DIO Single Read/Write,一中级 VI你可以在 Data Acquisition? Digital I/O模板中找到该 VI,
它是在我们上面讨论道的高级 VI的基础上作出来的。请记住:当你在循环中使用 DI/O时,
最好使用高级 VI以免象 DIO Single Read/WriteVI这样在循环中重复设置配置。
Figure 5-19,DIO Single Read/Write VI
Digital Single Read 与 Digital Single Write VI的执行是同步的; 当它们被调用后直到完成期间,其他 LabVIEW过程是不会被执行的。这种方式对于短急信息的传输来说是非常有效的,
但是当你想传输长数据流时就有可能长时间的占用计算机的资源。 在这种情况下你就可以使用下面将讲到的缓冲 DI/O。
例子 --- PC-PC 数据传输
你可以用有定时型 DI/O的数采板来完成通信应用,例如 PC-to-PC的数据传输。图 5-20
显示了使用两台都装有 DIO-32F数采板的计算机来完成 PC-to-PC的数据传输。在这个例子中
REQ 与 ACK线分别用于输入与输出的握手线信号。当软件调用操作且在 REQ线上接受到信号后,数采板就会执行一次数据传输。当执行完传输后数采板会在 ACK线上发出一个脉冲。
这样就可以保证数采板间数据传输的同步性。
Figure 5-20,DIO-32F 用于 PC到 PC 的数据传输
LabVIEW 框图
输出数采板
输入数采板
缓冲型 DI/O VI
假如需要大数量的数据传输,你也许希望使用非同步中断驱动式传输。这样不至于在传输数据时占用计算机的资源。使用这种方式传输数据时,一计算机内存缓冲被分配为后台线程输入或输出缓冲中。
中级 Data Acquisition? Digital I/O的模板中包含了用于建立数字量信号发生的 VI。表
5-3中显示的是缓冲式数字 IO程序设计的顺序,这些 VI与第四课表 4-1中的缓冲式模入和模出的程序设计顺序相类似。
表 5-3缓冲式数字 IO程序设计的顺序
DIO Config 设置的一组端口为输入或输出模式;创立数据缓冲,产生了任务唯一标识符,
它将会被下面的 DIO函数使用。
DIO Start 启动缓冲式 DIO操作。设定更新或读取的点数,当你输入 0时将连续操作。指定握手信号源:内部时钟用于信号发生,IO连接端口,或 RSTI连接端口。当执行信号发生时,
你也可以输入握手线信号的频率。
DIO Read 返回从数字量缓冲中扫描的数据;返回缓冲中的数据剩余量;返回在一定时限中操作的初始化是否成功信息。
DIO Write 用于输出操作中更新缓冲中的数据。当等侯的握手信号发生时,端口将被新的缓冲数据更新。假如在一定时限内握手信号没有出现,将返回一错误信息。
DIO Wait 等待与任务标识符 task ID.相关任务的数字量输入或输出操作的完成。
DIO Clear s停止操作,同时清除与 task ID任务相关的缓冲。
注意,当你使用这些 VI时,你的数采板必须支持握手信号。表 5-2显示了 NI公司生产的哪一些数采板支持握手信号。信号发生的功能只有 AT-DIO-32F,PCI-DIO-32HS,和
AT-DIO-32HS型号的数采板具有
下面的框图显示了使用缓冲式握手数字 IO VI的工作。每一个用于该框图的数字量 VI将在下面进行详细的讨论。
DIO Config VI,设置端口 1端口 1为一组输出组,同时为它们分配了数据缓冲。
DIO Write VI.将一个一维整形量数组存于缓冲中。 FOR循环使用自动索引输出方式创建了该数组。
DIO Start VI,设置 I/O接线端口为握手信号源,并启动输出操作。
DIO Wait VI.等待缓冲式输出操作完成。 DIO Clear VI.清除输出操作任务。
计数器
Counter I/O
对于一个成熟的数据采集和控制系统来说,它有一种非常重要的要求就是能操纵和协调多种不同时间参数和事件。这就需要某些硬件机构完成高精度的定时工作,那么这些机构中最基本的功能块就是计数器。 如果给予计数器非常精确的时钟你就可以把它应用到非常广泛的定时和计数应用之中去。例如:检测和分析数字波形,产生复杂的方波。
你可以在 NI的某些系列的多功能数采板上找到应用计数器的例子,那就是 AM9513A系统定时控制器。这个集成电路是由 5个 16位的计数器构成的,它们主要负责 DAQ操作的定时工作,如多用途定时及计数器应用。尽管 AM9513A是一多用途定时计数控制器,但它并不是专门为数据采集使用而专门设计的。因为 AM9513A仅有 5个计数器,假如你在运行某些同步操作时那么这些计数器将不够用,举个例子来说 AM9513A就没有足够的计数器来同时执行模拟输入、模拟输出和频率测量。
正是 AM9513A的局限性,所以 NI公司专门研制了数据采集控制器( System Timing
Controller (STC))用来控制 E系列的多功能数采板的定时操作。 DAQ-STC与现在其它公司生产的定时计数器相比,它具备有可扩展功能,低造价、低功耗的这些特点。这一块专用集成电路芯片总共有 10个 16位和 24位 20MHz的定时计数器。其中四个计数器用于控制模拟输入的定时操作,四个计数器用于模拟输出的定时操作;其它两个是留给用户使用的多用途,
UP/DOWN,24位 20MHz的定时计数器。
对于更高要求的定时计数操作,NI公司专门研发了 NI-TIO 集成电路芯片用于 6602和
445X系列数采板。这些定时计数器芯片是与 DAQ-STC相兼容的,同时又提供了其它的附加功能。每一个 NI-TIO芯片有四个能用于 80 MHz,20 MHz,100 kHz时基的 32位计数器,每一个计数器都有能被外部或内部信号控制的 GATE,UP/DOWN,SOURCE 输入口。如果使用预标定技术,NI-TIO能测量甚至频率高达 125MHz的连续,高速,重复信号的周期或频率。
因为直接低层编程使用定时计数器芯片是非常困难的,所以 LabVIEW提供了一系列高级的定时 /计数器库函数。在简化了定时 /计数器使用的同时并没有牺牲它们广泛的灵活性。
在 NI-DAQ6.5 有一个例程库,在该库中有每一种 NI定时 /计数器芯片的使用例子:
8253.llb,Am9513.llb,DAQ-STC.llb以及 NI-TIO.llb。下面将对计数器做一简单描述,接着将介绍 LabVIEW 中计数器 VI 以及使用计数器的例子。
计数器信号
计数器可以接收或输出 TTL兼容信号,一个 TTL高电位信号是被定义为其电位在 2.0和
5V之间的信号,TTL低电位是指其电位在 0到 0.8伏之间。一个能被计数器测得的信号,至少其特征不低于能被该计数器识别的最小的脉冲宽度,上伸时间、下降时间,请看图 6-1。
图 6-1计数器信号的特性参数
计数器操作
计数器是一能测量信号的变化过程或产生不同类型时间信号的设备。我们可以看一看如图 6-2所示的计数器的简化模型:一个 SOURCE输入口,一个 GATE输入口,一个 OUT 输出口,以及一个计数寄存器。数采板上分别对应的端口为,SOURCE n,GATE n,以及 OUT
n( n是指计数器的序号) 。
图 6-2,计数器的简化模型
你可以设置计数器对 SOURCE输入端口由高到低或由低到高的信号状态进行计数;并可以设置内部计数寄存器的计数方式为递增或递减方式;当你想知道信号状态改变的次数时,你就可通过读取内部计数寄存器的值即可知道。
GATE 口的输入端控制了计数器的计数操作。你可以将计数器设置为以下的几种门限工作方式:高电位时计数,低电位时计数,上升沿触发计数,下降沿触发计数,及无门限方式。高电位或低电位计数方式:只有当 GATE口的输入信号为高电位或低电位时,计数器才计数。上升沿触发计数或下降沿触发计数方:当 GATE 口接收到一由高到低或由低到高的状态变化信号后即开始计数。无门限方式:通过软件来初始化开始计数操作。
你可以使用计数器的 OUT口发生多种类型的波形,或者用于计数器的串级使用中,从而增大计数器的量程。 在一般模式下你可以设置计数器的端口输出一个脉冲或当计数寄存器已达到它的最大值时,输出一个切换状态作为一个终结计数。当接上一个时钟后你可以让计数器发出特定的频率和占空比的脉冲信号(一个占空比定义为,Phase 2 /[Phase 1 + Phase 2],
如图 6-3所示) 。输出的极性设置决定了初始化的 OUT口信号是低(正极性)或高(负极性) 。
图 6-3,计算脉冲的占空比
图 6-4显示了计数器 GATE 口工作为高电位计数时的情形,OUT口终结计数 显示了两种输出:脉冲,切换状态。
图 6-4,计数器 GATE 口工作为高电位计数
LabVIEW 计数器 VI
LabVIEW 计数器 VI 被分为了以下三个类型的模板,
Easy I/O VIs (Data Acquisition? Counter 模板 ):较简单的且经常使用的计数器 VI。如用于以下常用的定时计数操作:事件定时 /计数,产生单个脉冲,产生脉冲序列,测量脉冲宽度或周期以及频率测量。这些 VI使用时在前面板都有错误处理和详尽的操作指示。
Intermediate VIs (Data Acquisition? Counter? Intermediate Counter
模板 ):主要用于设置和控制计数器的操作,这些 VI比 Easy I/O VI更灵活。所有的中级计数器 VI都使用了 LabVIEW的错误处理,过你可以建立自己的错误处理路径。这些 VI使用时在前面板都详尽的操作指示。
Advanced VIs (Data Acquisition? Counter? Advanced Counter
模板 ):高级计数器 VI主要用于作为创建其他数字 VI的基本模块。这些 VI是最灵活也是最复杂的。典型的来说,用于需要多设置和控制的应用中。象中级计数器 VI一样,使用高级计数器 VI时你也可以建立自己的错误处理路径。
注意 当你打开 Windows? Show VI Info..,菜单后,便会弹出一窗口告诉你如何连接 source
口,gate口以及 output口。
在大多数情况下,我们使用 Easy I/O 计数器 VI,下面部分将介绍在不同情况下使用这些 VI。在后面的章节中将介绍中级和高级 VI的使用。
事件定时和计数
在本部分将介绍计数器的常用操作:事件定时 /计数,产生单个脉冲,产生脉冲序列,
测量脉冲宽度或周期以及频率测量。每个应用程序都将用到一个或两个 Data Acquisition
Counter VI 。在 LabVIEW中都有例程显示如何使用其中的每个 VI。
你可以把 Easy I/O VI Count Events or Time 用于事件定时 /计数 (图 6-5),例如 SOURE
输入口信号上升或下降沿出现的次数。 device 和 counter 输入端指定了是那一块数采板的那一个计数器端口将接收事件。 Source edge 确定该事件是上升沿还是下降沿。当 event
source/timebase 的输入端值小于或等于零时,计数器将对 SOURE口输入的信号进行计数。
当 event source/timebase被设置为有效的内部时钟频率时,计数器将对 SOURE口输入的内部时钟信号进行计数。根据你使用的数采板来决定你可用的有效内部时钟频率,如使用
DAQ-STC芯片的数采板其内部有效时钟频率可为 20MHz和 100KHz。 Counter size输入设置了最大计数容量,当超过该值后计数器将会溢出并重新清零。 DAQ-STC芯片上 24位的计数器在溢出前其最大计数容量为 16M。 start/restart输入端控制计数器启动 /停止操作。
图 6-5.事件定时 /计数 VI
count 输出端返回的是当前计数器寄存器的值。 seconds since start 返回自计数器启动后的时间值。 seconds since last call 返回自计数器寄存器被读取后的时间值。只有当 event
source/timebase 输入端为有效内部时钟时 seconds since start 与 seconds since last call的返回值才有实际意义。
练习 6-1
目标,对一已知的时钟信号的上升沿进行计数
1.打开 Exercise\lesson6.llb\Event countingCounting/Timing.vi,查看该 VI的前面板和后面框图。该 VI允许你重复启动或停止 Counter 1。这个计数器是对频率为 100 KHz的内部时钟的上升沿进行计数的。 Status输出指示了计数器当前是否在运行。 Count Events or Time输出全部都显示在前面板上。
前面板
程序框图
Count Events or Time VI (Data Acquisition? Counter 模板 )。
当你按下前面板 Start Counter 按扭后即启动计数器对内部时钟信号上升沿进行计数。在每次的 While循环中,该 VI都读取计数器寄存器的值并计算计数器被启动后的时间和上次被读取后的时间值,假如你按下前面板 Stop Counter按扭即停止计数器的运行。
Wait Until Next ms Multiple 函数 (Time & Dialog 模板 )。在本练习中控制 While循环的运行速度和每隔 1秒监视计数器的状态。
Status 局部变量 (Structures 模板 ).。在本练习中设置前面板的状态字符串来显示计数器是在计数还是在等候。
2.运行 VI。当你按下 Start Counter按扭后,即看到 Status输出为 Counter is counting。同时,
Counter Register Value 的显示应为每隔一秒递增 100,000。 Time Since Start显示你启动计数器后的时间; Time Since Last Call显示上次计数器寄存器被读取后的时间,因为 While循环是每隔一秒运行一次故该值应始终为 1。当你按下 Stop Counter后即停止计数器的运行,此时 Status显示为 Counter is waiting。
3.当按下 Quit按扭后即从该 VI中退出。关闭该 VI,不要保存任何改动。
练习 6-1结束,
发生脉冲
发生脉冲是计数器另一教常用的功能。你可以在 OUT口输出一个或一串脉冲。你可以使用 Generate Delayed Pulse VI发生一单个脉冲; Generate Pulse Train VI发生一脉冲序列。着两个 VI都在 Data Acquisition? Counter模板中。使用这两个 VI时你需要设定以下参数:脉冲极性,延迟,幅宽(延迟和幅宽之和为脉冲宽度)以及占空比。脉冲极性(如图 6-6所示)
决定了脉冲为高还是低。
Figure 6-6,脉冲极性高低的例子
注意 占空比定义如下,Duty cycle = Width / (Delay + Width),
发生单个脉冲
Generate Delayed Pulse VI (图 6-7) 输出一由 pulse polarity,pulse delay 和 pulse
width 参数决定的单个脉冲。 device 和 counter 输入端指定了是那一块数采板的那一个计数器输出单个脉冲。 gate mode设置了计数器工作的门限模式 (具体使用时,请给计数器的 GATE
输入口接上一外部的门限信号 )。 Timebase source决定了那一时钟用于延迟和幅宽。假如你使用内部时钟,那么数采板上的时钟作为延迟和幅宽的计时可达到秒的量级。假如你使用外部时钟,那么请你确保把外部的时基信号连接到计数器的 SOURCE端口上,此时延迟和幅宽的计时是以外部时基的周期数为单位的。 taskID输出包含了产生该脉冲所有设置的信息,是标识该任务的标识符。你可以把 taskID输出作为中级 Counter Start VI的输入参数从而可再发生同样的脉冲。
Figure 6-7,产生延迟脉冲的 VI
发生脉冲序列
用 Generate Pulse Train VI (图 6-8)可输出一系列由 pulse polarity,frequency,和 duty
cycle输入参数决定的脉冲序列。 Device,counter,和 gate mode输入参数的意义与 Generate
Delayed Pulse VI同名参数的意义相同。输入参数 number of pulses设定了脉冲序列的长度。假如你把 number of pulses设为零,那么该 VI将发生连续的脉冲序列。 TaskID输出包含了产生该脉冲序列所有设置的信息,是标识该任务的标识符。当你产生一有限长度的脉冲序列时将使用的是 taskID of counter-1返回值作为任务标识符。你可以把 taskID或 taskID of counter-1输出作为中级 Counter Start VI的输入参数从而可再发生同样的脉冲序列。
Figure 6-8,发生脉冲序列 VI
当你使用计数器发生一脉冲或脉冲序列时,用于启动计数器操作的信号与控制脉冲周期的时基信号并不是同步的。 在大多数情况下启动的脉冲信号并不是恰好在时基信号的上升沿时出现的。这也就是说,在启动发生脉冲时会有大致一个时基时钟周期的误差。图 6-9显示了使用高电位门限触发启动计数器操作时的这种误差。 这种误差在使用软件提供启动计数器操作信号时也存在。
Figure 6-9,启动计数器发生脉冲序列时的不确定性
练习 6-2
目标,使用计数器发生一个脉冲
在运行该练习之前,请将试验盒上的 GPCTR1 OUT接线端连线到模拟输入 ch0上。
1,打开 Exercise\Lesson6..llb\Counter Single Pulse VI 查看该程序的前面板和后面板框图
前面板
程序框图
2,打开并运行 Read and Chart VI,该 VI 会连续采集模入通道 1并将采得的数据显示到图表中去。当 Read and Chart运行后,运行 Counter Single Pulse VI。
3,在 Counter Single Pulse 前面板上设置脉冲的参数,按下 Generate Pulse 按扭后,你将在图表中看到计数器发生的脉冲。
4,停止这两个 VI的运行,在为保存任何改动的选择下关闭 Counter Single Pulse 。请不要关闭 Read and Chart.,你将在下面的练习中使用到该 VI。
练习 6-2结束
练习 6-3
目标,使用计数器发生一个脉冲序列
在运行该练习之前,
请将试验盒上 GPCTR1 OUT接线端接线到模拟输入的 ACH0上。
把试验盒上的 GPCTR0 OUT接线端接线到 PFI4接线端(计数器 1GATE口) 。
1,打开 Exercise\lesson6.llb\Counter Pulse Train VI 查看该程序的前面板和后面板框图
Generate Pulse Train VI (Data Acquisition? Counter 模板 )。在本练习中该 VI用产生一由前面板参数决定的脉冲序列。假如发生的脉冲序列是连续的,你可以通过按下前面板的 Stop
按扭来停止脉冲序列的发生。
前面板
程序框图
2,打开并运行 Read and Chart VI,该 VI 会连续采集模入通道 1并将采得的数据显示到图表中去。当 Read and Chart运行后,在 Counter Pulse Train 前面板上设置脉冲的参数,
运行 Counter Pulse Train VI,在图表中观察计数器发生的脉冲序列。
3,改变脉冲序列参数并输入,观察这些参数对脉冲序列的影响。
4,停止并关闭这两个 VI,请不要保存任何改动。
练习 6-3结束
脉冲宽度测量
你可以使用计数器来测量脉冲或脉冲序列的特性参数。 Measure Pulse Width or Period
VI (Data Acquisition? Counter 模板 )可用来测量连接到计数器 GATE口信号整个脉冲的宽度或幅宽的宽度。 Measure Frequency VI (Data Acquisition? Counter 模板 ) 可用来测量连接到计数器 SOURCE口脉冲序列信号的频率。这两个 VI都用到了计数器的门限计数功能 。
脉冲宽度或周期的测量
当你测量一脉冲宽度时,你需将被测的脉冲信号 Tpw 连接到计数器的 GATE口;将一已知频率的信号 Ts连接到计数器的 SOURCE口,如图 6-10所示。当计数器被设为高门限计数模式时,计数器会在 GATE口信号开始时对 SOURCE口的脉冲个数进行计数在 GATE口信号结束时停止计数。 此时你就可以用计数器寄存器的计数值乘以 SOURCE口信号的周期即可算出被测信号的脉冲宽度。用 Measure Pulse Width or Period VI时 SOURCE口用的是内部时钟,故你只需将被测信号接到计数器的 GATE口上即可。
Figure 6-11,Measure Pulse Width or Period VI
Measure Pulse Width or Period VI 输入参数 device 和 counter决定了是那一块数采板的那一个计数器用于测量脉冲信号的参数。 Type of measurement输入参数决定了你是想测量整个脉冲的宽度还是仅测量脉冲的高电位部分或脉冲的低电位部分的宽度。 timebase决定了用于被计数的内部时钟。若计数操作未在 time limit 时间限制内完成,timeout 输出为 TRUE。
Pulse width/period返回测量的宽度或周期(以秒为单位),count返回计数器寄存器的值。若
counter overflow? 返回值为 TRUE,这是有计数器溢出造成,此时你应当降低 timebase内部时钟的频率。 valid? 输出显示了是否有足够的内部时钟计数确保测量的脉冲宽度或周期值正确。
Figure 6-11,Measure Pulse Width or Period VI
练习 6-4
目标,使用计数器测量脉冲宽度或周期
运行程序前,请确保以做了下面的信号连接,
将试验盒上的方波输出 PULSE接线端引出方波信号到 PFI4(记数器 GATE口接上一方波信号。
1,打开 Exercise\lesson6.llb\Pulse Measurement VI,查看该程序的前面板和后面板框图。该
VI使用 Counter 1来测量连接到 GATE输入口信号的脉冲宽度或周期。计数器 SOURCE口接入的内部时 钟是由 Type of Measurement输入参数来决定的。
前面板
程序框图
Measure Pulse Width or Period VI (Data Acquisition?Counter
模板 )。在本练习中,该 VI使用来测量接到 Counter 1 GATE口上信号的脉冲宽度或周期的。其返回的错误信息可显示到 VI的前面板。
Attribute Node.。该属性接点是用来根据所选的测量类型来控制前面板与之对应的 Pulse
Width和 Pulse Period 控件是否变灰。你把鼠标放到前面板 Pulse Width和 Pulse Period
控件上后,单击右键从弹出的快捷菜单中选择 Create Attribute Node 即可创建对应的属性接点。请将这两个属性接点设为 Disabled(属性接点的操作是在 LabVIEW Basics II
Course 中详细介绍的) 。
2,请沿逆时针方向调节 DAQ 信号附件上的频率旋扭大致为 95~125Hz。把测量方式设为
High Phase后运行 VI,此时你应测得的脉冲幅宽大致为 0.008 到 0.0105秒。把测量方式设为 Low Phase后运行 VI,此时你应测得的脉冲宽度应与 High Phase方式相同。因为 DAQ
信号附件上发出方波的占空比是 0.5。
3,把测量方式设为 Rising to Rising后运行 VI,此时你应测得的脉冲宽度大致为 0.016 到
0.021秒或者是幅宽的两倍。因为此时测量的是整个信号的宽度。
4,将测量方式设为 High Phase 并旋动 DAQ信号附件上的频率按扭至非常高的频率,将 DAQ
信号附件上频率选择档设为最高的范围 (13 kHz–1 MHz)。此时信号方波的幅宽约为 500
ns 周期约为 1.0 ms 。因为计数器使用内部时钟为 20 MHz 故我们仍得到有效的测量结果。在后面板框图中将 timebase设为 100,000 Hz,运行后程序将返回 timeout 错误。因为计数器不能对 GATE口信号进行足够的计数,从而得不到有效的测量结果。
5,停止并关闭 VI,请不要保存任何改动。
练习 6-4 结束
频率测量
计数器也可用于测量脉冲序列的频率。通过对在给定的已知时间内的脉冲串个数进行计数即可计算出被测信号的频率。 给定时间间隔 TG是由连接到计数器 GATE口的脉冲信号控制的,如图 6-12。接到 GATE口必须是已知幅宽的脉冲信号,该信号是由外部信号源或数采板上第二个计数器提供的。 你用已知信号幅宽除以计数器在门限设置模式下读取的计数器寄存器的数值即可算出被测信号的频率。使用 Measure Frequency VI时,数采板上第二计数器提供门限脉冲,所以你需要将第二个计数器的 OUT输出口连接到第一个计数器的 GATE口,
将被测信号接到第一个计数器的 SOURCE口上。
注意 第二个计数器一般是使用数采板上紧邻使用计数器的上一个计数器。例如:你用于计数的计数器是 Counter 1,那么提供门限脉冲信号的计数器就是 Counter 0即把 OUT0接到
GATE1。
图 6-12,用于测量频率的信号连接
你可以使用 Measure Frequency VI (图 6-13)来测量频率较高的脉冲序列信号的频率 。
输入参数 device 和 counter决定了是那一块数采板的那一个计数器用于测量脉冲信号的参数。 Gate width设置了由第二个计数器 (counter-1)所发脉冲的幅宽(以秒为单位) 。 Counter
size设置了计数器对一未知信号能进行的最大计数值(对于 24位计数器来说为 2的 24次方) 。
假如你需要对 Measure Frequency VI 中的 counter-1进行门限触发,请给 counter-1计数器的
GATE输入口上接入触发信号; 同时你必须正确的设置 gate mode 与 maximum delay to gate
参数。例如:当这些设置好了,只要 counter-1计数器在其 GATE输入口上接收到一上升沿触发信号后,counter-1即在其 OUT口输出一已知的接于 counter GATE输入口的门限脉冲。
Frequency返回测得的被测信号的频率(以 Hz为单位) 。 Valid? 返回参数指示是否有错误发生。
图 6-13,Measure Frequency VI
练习 6-5
目标,使用计数器测量未知信号的频率
在运行该练习之前,请确保了你的 DAQ信号附件已有了下面的连接,
把一方波信号接到 Counter 1的 SOURCE口上。
把 Counter 0的 OUT口输出连接到 Counter 1的 GATE口输入上。
1,打开并查看 Exercise\Lesson6.llb\FrequencyMeasurement VI.。 该 VI将测量连接到 Counter 1
上脉冲序列信号的频率。 Counter 1 在其 GATE口输入为高电位时会对其 SOURCE口的脉冲个数进行计数。你也可以把 Counter 1的门限计数方式设为低电位模式,即当其 GATE
口输入为低电位时会对其 SOURCE口的脉冲个数进行计数。你可以在 VI的前面板上通过
GateWidth来设置门限脉冲的幅值宽度,LabVIEW会自动设置 Counter 0输出门限脉冲。
Measure Frequency VI (Data Acquisition? Counter 模板 )。 本练习中这个 VI将用来测量连接到 Counter 1的 SOURCE口的信号的频率。这个 VI会返回错误信息并显示的前面板上。这个
VI会自动根据前面板 Gate Width参数来设置另一计数器输出已知幅宽的脉冲序列信号。
Unbundle 函数 (Cluster 模板 )。将用于对 Measure Frequency VI 返回的错误信息进行解包并显示到前面板上。
2,请逆时针旋转 DAQ信号附件的频率旋扭。把 Gate Width设为 1后运行程序。此时频率的测量值应在 95 Hz与 125 Hz之间。重新运行几次程序,数次同样频率信号频率的测量值有可能有稍微的差别。这是由于门限信号电位为高时的时刻与 SOURCE口出现第一个用于计数脉冲时刻的时间差异不同而造成的,如图 6-14所示。
Figure 6-14,导致频率测量不精确的原因
3,请将 DAQ信号附件的频率旋扭旋到最大频率处,把 Gate Width设为 20秒后运行该 VI。你将会看到一计数器寄存器溢出的错误信息。这是由于而被测信号频率过高,从而导致在门限幅宽为 20秒期间计数器对被测信号计数已超过其计数寄存器的最大计数容量,从而出现溢出的错误信息。当 DAQ信号附件的频率旋扭旋到最大处,其产生信号的频率约为
1 MHz。
4,关闭 VI,请不要保存任何改动。
练习 6-5 结束
其他附加有用的Counter VI
计数器的分频设置
Down Counter or Divider Config VI (Data Acquisition? Counter?
Intermediate Counter 模板 ) 是一当预设事件次数出现后可发生脉冲的 VI。例如:你把
timebase/timebase divisor设为 100 Hz / 50,那么计数器将每隔 50个时基脉冲在 OUT发出一个脉冲或切换电位状态,其频率应为 50*100 Hz = 2 s 。当你启动该操作时,请将该 VI的 taskID
输出接到 Counter Start VI (Data
Acquisition? Counter? Intermediate Counter 模板 )上。
Figure 6-15,Down Counter or Divider Config VI
CTR Control
The CTR Control VI (Data Acquisition? Counter? Advanced Counter
模板 ) 可用于由 control code 输入参数决定的关于计数器控制方面的所有操作:启动,停止,
读取以及重置计数器。 CTR Control VI 也能控制数采板上的 FREQ_OUT通道输出根据 fout
data参数指定频率的占空比为 0.5的脉冲序列且并不占用数采板上的计数器。你可以通过设定 control code为 7 (enable FREQ_OUT)来启动 FREQ_OUT输出;设定 control code为 8(disable
FREQ_OUT)来停止 FREQ_OUT输出。
Figure 6-16,CTR Control VI
CTR Group Config
CTR Group Config VI (Data Acquisition? Counter? Advanced Counter 模板 )可将一个或多个计数器合成为一组。 Device设定数采板的设备号,group是根据 counter list数组设给该组计数器的唯一组号。 task ID返回值是标识该任务的标识符; error in 和 error out包含有错误信息。请记住该 VI需在所有计数器操作前运行。
Figure 6-17,CTR Group Config VI
CTR Mode Config
CTR Mode Config VI (Data Acquisition? Counter? Advanced
Counter 模板 ) 根据 task ID,config mode,source,timebase signal,gate parameters,output
type,和 output polarity参数来对计数器进行设置。 error in 和 error out包含有错误信息。
该 VI并不启动计数器操作。在计数器运行时的情况下,你并不需要使用该 VI,除非你想改变计数器的门限和输出工作状态。
Figure 6-18,CTR Mode Config VI
下面你将使用 Advanced Counter VI来跟踪一正交编码器的位置。但是首先要提醒你,
关于正交编码器的操作只能用于 DAQ-STC和 NI-TIO芯片。
正交数码盘
数码盘是一能将线性或旋转位移转变为数字或脉冲信号的变送器,通常安装在旋转的轴上。它能发出对应于轴旋转运动状态的脉冲序列信号。正交数码盘是较常用的有两通道用来监测轴位置的递增式数码盘。 对于转子每旋转一定角度,递增式数码盘将会产生一个脉冲。
因此,递增数码盘的精度是由转子旋转一周中有数码盘能发生多少个脉冲数目来决定的。一般常使用的数码盘并不输出绝对位置信息。 但是正交数码盘使用了两个相位差为 90度的跟踪通道(如图 6-19),所以正交数码盘上的通道 A和通道 B可以显示旋转的位置和方向这两个信息。
Figure 6-19,正交编码器输出通道 A 和 B
假如通道 A超前通道 B,那么旋转的方向为顺时针方向;假如通道 B超前通道 A,那么旋转的方向为逆时针方向。这样通过监测通道 A,B信号的脉冲个数和相位差,你就可以跟踪旋转的位置和方向。
DAQ-STC 计数器的增 / 减计数输入
NI E系列数采板上的 DAQ-STC 定时 /计数器可用于计数器的增 /减计数,DAQ-STC上的计数器除了有 SOURCE口和 GATE口外还有 UP_DOWN口。当 UP_DOWN口接入的 TTL信号为高电位时,计数器将会递增计数;当 UP_DOWN口接入的 TTL信号为低电位时,计数器将会递减计数。这样,我们就可以来监测正交数码盘的旋转方向。
假如正交数码盘输出的直接是 TTL信号,那么你可以将输出的信号直接接到 DAQ-STC
或 NI-TIO上。否则你需要在数码盘和计数器之间加上信号调理电路。通道 A将接到计数器的
SOURCE口上,通道 B将接到 UP_DOWN口上。当数码盘顺时针旋转时,A将超前 B 90度。
这就意味着当通道 A信号的状态为由高到低时,通道 B上信号为高电位状态,此时计数寄存器将对 A的下降沿切换状态进行递增计数;当数码盘逆时针旋转时,B将超前 A90度。这就意味着当通道 A信号的状态为由高到低时,通道 B上信号为低电位状态,此时计数寄存器将对 A的下降沿切换状态进行递减计数。
你现在可以使用 Counter 0来跟踪 DAQ信号附件上旋转正交数码盘。关于正交数码盘的详细资料,请查阅 Application Note 084,Using Quadrature Encoders with E Series DAQ Boards。
Measure frequency-Easy(9513).vi
1
device
1
counter
0.00047996
period (s)
YES
valid?
2.00
gate width (s)
2083.500
frequency (Hz)
NO
overflow?
NO
timeout?
one counter
number of counters to use
For instructions select
File >> VI Properties >> Documentation
1,1 虚拟仪器概述
虚拟仪器( virtual instrumention)是基于计算机的仪器。计算机和仪器的密切结合是目前仪器发展的一个重要方向。粗略地说这种结合有两种方式,一种是将计算机装入仪器,其典型的例子就是所谓智能化的仪器。随着计算机功能的日益强大以及其体积的日趋缩小,这类仪器功能也越来越强大,目前已经出现含嵌入式系统的仪器。另一种方式是将仪器装入计算机。以通用的计算机硬件及操作系统为依托,实现各种仪器功能。虚拟仪器主要是指这种方式。下面的框图反映了常见的虚拟仪器方案。
虚拟仪器的主要特点有,
null 尽可能采用了通用的硬件,各种仪器的差异主要是软件。
null 可充分发挥计算机的能力,有强大的数据处理功能,可以创造出功能更强的仪器。
null 用户可以根据自己的需要定义和制造各种仪器。
虚拟仪器实际上是一个按照仪器需求组织的数据采集系统。 虚拟仪器的研究中涉及的基础理论主要有计算机数据采集和数字信号处理。目前在这一领域内,使用较为广泛的计算机语言是美国 NI 公司的 LabVIEW。
虚拟仪器的起源可以追朔到 20 世纪 70 年代,那时计算机测控系统在国防、航天等领域已经有了相当的发展。 PC 机出现以后,仪器级的计算机化成为可能,甚至在 Microsoft 公司的 Windows 诞生之前,NI 公司已经在 Macintosh 计算机上推出了 LabVIEW2.0 以前的版本。
对虚拟仪器和 LabVIEW 长期、系统、有效的研究开发使得该公司成为业界公认的权威。
普通的 PC 有一些不可避免的弱点。用它构建的虚拟仪器或计算机测试系统性能不可能太高。目前作为计算机化仪器的一个重要发展方向是制定了 VXI 标准,这是一种插卡式的仪器。每一种仪器是一个插卡,为了保证仪器的性能,又采用了较多的硬件,但这些卡式仪器本身都没有面板,其面板仍然用虚拟的方式在计算机屏幕上出现。这些卡插入标准的 VXI
机箱,再与计算机相连,就组成了一个测试系统。 VXI 仪器价格昂贵,目前又推出了一种较为便宜的 PXI 标准仪器。
虚拟仪器研究的另一个问题是各种标准仪器的互连及与计算机的连接。 目前使用较多的是 IEEE 488 或 GPIB 协议。未来的仪器也应当是网络化的。
1,2 LabVIEW 是什么?
LabVIEW( Laboratory Virtual instrument Engineering)是一种图形化的编程语言,它广泛地被工业界、学术界和研究实验室所接受,视为一个标准的数据采集和仪器控制软件。
LabVIEW 集成了与满足 GPIB,VXI,RS-232 和 RS-485 协议的硬件及数据采集卡通讯的全部功能。它还内置了便于应用 TCP/IP,ActiveX 等软件标准的库函数。这是一个功能强大且灵活的软件。利用它可以方便地建立自己的虚拟仪器,其图形化的界面使得编程及使用过程被测对象信号调理数据采集卡虚拟仪器面板数据处理都生动有趣。
图形化的程序语言,又称为“G”语言。使用这种语言编程时,基本上不写程序代码,
取而代之的是流程图或流程图。它尽可能利用了技术人员、科学家、工程师所熟悉的术语、
图标和概念,因此,LabVIEW 是一个面向最终用户的工具。它可以增强你构建自己的科学和工程系统的能力,提供了实现仪器编程和数据采集系统的便捷途径。 使用它进行原理研究、
设计、测试并实现仪器系统时,可以大大提高工作效率。
利用 LabVIEW,可产生独立运行的可执行文件,它是一个真正的32位编译器。像许多重要的软件一样,LabVIEW 提供了 Windows,UNIX,Linux,Macintosh 的多种版本。
1,3 LabVIEW 的运行机制
1,3.1 LabVIEW 应用程序的构成
所有的 LabVIEW 应用程序,即虚拟仪器( VI),它包括前面板( front panel),流程图
( block diagram)以及图标 /连结器 (icon/connector)三部分。
前面板
前面板是图形用户界面,也就是 VI 的虚拟仪器面板,这一界面上有用户输入和显示输出两类对象,具体表现有开关、旋钮、图形以及其他控制( control)和显示对象( indicator) 。
图 1 所示是一个随机信号发生和显示的简单 VI 是它的前面板,上面有一个显示对象,以曲线的方式显示了所产生的一系列随机数。 还有一个控制对象——开关,可以启动和停止工作。
显然,并非简单地画两个控件就可以运行,在前面板后还有一个与之配套的流程图。
流程图
流程图提供 VI 的图形化源程序。在流程图中对 VI 编程,以控制和操纵定义在前面板上的输入和输出功能。流程图中包括前面板上的控件的连线端子,还有一些前面板上没有,
但编程必须有的东西,例如函数、结构和连线等。图1-2是与图1-1对应的流程图。我们可以看到流程图中包括了前面板上的开关和随机数显示器的连线端子,还有一个随机数发生器的函数及程序的循环结构。随机数发生器通过连线将产生的随机信号送到显示控件,为了使它持续工作下去,设置了一个 While Loop 循环,由开关控制这一循环的结束。
控制对象
(输 入 )
显示对象
(输出 )
图1-1 随机信号发生器的前
如果将 VI 与标准仪器相比较,那么前面板上的东西就是仪器面板上的东西,而流程图上的东西相当于仪器箱内的东西。在许多情况下,使用 VI 可以仿真标准仪器,不仅在屏幕上出现一个惟妙惟肖的标准仪器面板,而且其功能也与标准仪器相差无几。
图标 /连接器
VI 具有层次化和结构化的特征。一个 VI 可以作为子程序,这里称为子 VI( subVI),
被其他 VI 调用。图标与连接器在这里相当于图形化的参数,详细情况稍后介绍。
1.2.2 LabVIEW 的操作模板
在 LabVIEW 的用户界面上,应特别注意它提供的操作模板,包括工具( Tools)模板、
控制( Controls)模板和函数( Functions)模板。这些模板集中反映了该软件的功能与特征。
下面我们来大致浏览一下。
工具模板( Tools Palette)
该模板提供了各种用于创建、修改和调试 VI 程序的工具。如果该模板没有出现,则可以在 Windows 菜单下选择 Show Tools Palette 命令以显示该模板。当从模板内选择了任一种工具后,鼠标箭头就会变成该工具相应的形状。当从 Windows 菜单下选择了 Show Help Window 功能后,把工具模板内选定的任一种工具光标放在流程图程序的子程序( Sub VI)或图标上,就会显示相应的帮助信息。
下述工具中注意1和2的区别,2用于编程时,1用于运行程序时。
4是一个特有的工具,它并不是一个简单的画线工具,而是一个符合 LabVIEW 语言规定的对象连接工具。
工具图标有如下几种,
函数:随机数发生器
结构:循环
与前面板控件对应的连线端子
与前面板控件对应的连线端子
图1-2 随机信号发生器的流
下面的两个模板是多层的,其中每一个子模板下还包括多个对象。
控制模板( Control Palette)
注意:只有打开前面板时才能调用该模板
该模板用来给前面板设置各种所需的输出显示对象和输入控制对象。每个图标代表一类子模板。如果控制模板不显示,可以用 Windows 菜单的 Show Controls Palette 功能打开它,也可以在前面板的空白处,点击鼠标右键,以弹出控制模板。
控制模板如左图所示,它包括如下所示的一些子模板。子模板中包括的对象,我们在功能中用文字简要介绍。
图标 名称 功 能
1
Operate Value
(操作值)
用于操作前面板的控制和显示。使用它向数字或字符串控制中键入值时,工具会变成标签工具
2
Position/Size/Sele
ct (选择)
用于选择、移动或改变对象的大小。当它用于改变对象的连框大小时,会变成相应形状。
3
Edit Text(编辑文本)
用于输入标签文本或者创建自由标签。当创建自由标签时它会变成相应形状。
4
Connect Wire(连线)
用于在流程图程序上连接对象。如果联机帮助的窗口被打开时,把该工具放在任一条连线上,就会显示相应的数据类型。
5
Object Shortcut
Menu(对象菜单)
用鼠标左键可以弹出对象的弹出式菜单。
6
Scroll Windows
(窗口漫游)
使用该工具就可以不需要使用滚动条而在窗口中漫游。
7
Set/Clear
Breakpoint(断点设置/清除)
使用该工具在 VI 的流程图对象上设置断点。
8
Probe Data(数据探针)
可在框图程序内的数据流线上设置探针。通过控针窗口来观察该数据流线上的数据变化状况。
9
Get Color(颜色提取)
使用该工具来提取颜色用于编辑其他的对象。
10
Set Color(颜色设置)
用来给对象定义颜色。它也显示出对象的前景色和背景色。
功能模板 (Functions Palette)
注:只有打开了流程图程序窗口,才能出现功能模板。
功能模板是创建流程图程序的工具。该模板上的每一个顶层图标都表示一个子模板。
若功能模板不出现,则可以用 Windows 菜单下的 Show Functions Palette 功能打开它,也可以在流程图程序窗口的空白处点击鼠标右键以弹出功能模板。
功能模板如右图所示,其子模块如下所示。 (个别不常用的子模块未包含)
图标 子模板名称 功 能
1
Numeric(数值量) 数值的控制和显示。包含数字式、指针式显示表盘及各种输入框。
2
Boolean(布尔量) 逻辑数值的控制和显示。包含各种布尔开关、按钮以及指示灯等。
3
String & Path(字符串和路径)
字符串和路径的控制和显示。
4
Array & Cluster
(数组和簇)
数组和簇的控制和显示。
5
List & Table(列表和表格)
列表和表格的控制和显示
6
Graph(图形显示)
显示数据结果的趋势图和曲线图。
7
Ring & Enum(环与枚举)
环与枚举的控制和显示。
8
I/O(输入 /输出功能)
输入 /输出功能。于操作 OLE,ActiveX 等功能。
9
Refnum 参考数
10
Digilog
Controls(数字控制)
数字控制
11
Clussic
Controls(经典控制)
经典控制,指以前版本软件的面板图标。
12
Activex 用于 ActiveX 等功能。
13
Decorations(装饰)
用于给前面板进行装饰的各种图形对象。
14
Select a
Controls(控制选择)
调用存储在文件中的控制和显示的接口。
15
User Controls
(用户控制)
用户自定义的控制和显示。
图标 子模板名称 功 能
1
Structure(结构) 包括程序控制结构命令,例如循环控制等,以及全局变量和局部变量。
2
Numeric(数值运算)
包括各种常用的数值运算,还包括数制转换、三角函数、对数、复数等运算,以及各种数值常数。
3
Boolean(布尔运算)
包括各种逻辑运算符以及布尔常数。
4
String(字符串运算)
包含各种字符串操作函数、数值与字符串之间的转换函数,以及字符 (串 )常数等。
5
Array(数组)
包括数组运算函数,数组转换函数,以及常数数组等。
6
Cluster(簇)
包括簇的处理函数,以及群常数等。这里的群相当于
C 语言中的结构。
7
Comparison (比较)
包括各种比较运算函数,如大于、小于、等于。
8
Time & Dialog(时间和对话框)
包括对话框窗口、时间和出错处理函数等。
9
File I/O(文件输入 /输出)
包括处理文件输入 /输出的程序和函数。
10
Data
Acquisition(数据采集)
包括数据采集硬件的驱动,以及信号调理所需的各种功能模块。
11
Waveform(波形) 各种波形处理工具
12
Analyze(分析) 信号发生、时域及频域分析功能模块及数学工具 。
13
Instrument I/O
(仪器输入 /输出)
包括 GPIB(488,488.2)、串行,VXI 仪器控制的程序和函数,以及 VISA 的操作功能函数。
14
Motion & Vision
(运动与景像)
15
Mathematics(数学)
包括统计、曲线拟合、公式框节点等功能模块,以及数值微分、积分等数值计算工具模块。
16
Communication
(通讯)
包括 TCP,DDE,ActiveX 和 OLE 等功能的处理模块。
17
Application
Control(应用控制)
包括动态调用 VI、标准可执行程序的功能函数。
18
Graphics & Sound
(图形与声音)
包括 3D,OpenGL、声音播放等功能模块。包括调用动态连接库和 CIN 节点等功能的处理模块。
19
Tutorial(示教课程)
包括 LabVIEW 示教程序。
20
Report
Generation(文档生成)
21
Advanced(高级功能)
22
Select a VI(选择子 VI)
23
User Library(用户子 VI 库)
1.4 LabVIEW 的初步操作
1.4.1 创建 VI 和调用子 VI
我们通过例子来说明如何创建一个 VI。
练习1-1,
建立一个测量温度和容积的 VI,其中须调用一个仿真测量温度和容积的传感器子 VI。
步骤如下,
1.选择 File?New,打开一个新的前面板窗口。
2.从 Controls?Numeric 中选择 Tank 放到前面板中。
3.在标签文本框中输入“容积”,然后在前面板中的其他任何位置单击一下。
4.把容器显示对象的显示范围设置为 0.0 到 1000.0。
a,使用文本编辑工具( Text Edit Tool),双击容器坐标的 10.0 标度,使它高亮显示。
b,在坐标中输入 1000,再在前面板中的其他任何地方单击一下。 这时 0.0 到 1000.0 之间的增量将被自动显示。
5,在容器旁配数据显示。
将鼠标移到容器上,点右键,在出现的快速菜单中选 Visible
Iterms?Digital Display 即可。
6.从 Controls?Numeric 中选择一个温度计,将它放到前面板中。设置其标签为“温度”,显示范围为 0 到 100,同时配数字显示。可得到如下的前面板图。
图1-3 练习1-1的前面板图
7,Windows?Show Diagram 打开流程图窗口。从功能模板中选择对象,将它们放到流程图上组成下图(其中的标注是后加的)。
随机数发生器
乘法函数数值常数
进程监视器图1-4 练习1-1的流程图
该流程图中新增的对象有两个乘法器、两个数值常数、一个随机数发生器、一个进程监视器,温度和容积对象是由前棉板的设置自动带出来的。
a,乘法器和随机数发生器由 Functions?Numeric 中拖出,尽管数值常数也可以这样得到,但是建议使用 c 中的方法更好些。
b,进程监视器( Process Monitor)不是一个函数,而是以子 VI 的方式提供的,它存放在 LabVIEW\Activity 目录中,调用它的方法是在 Functions?Select a VI
下打开 Process Monitor,然后在流程图上点击一下,就可以出现它的图标。
注意,LabVIEW 目录一般在 Program Files\National Instruments\目录下。
8.用连线工具 将各对象按规定连接。 a 中的遗留问题创建数值常数对象的另一
种方法是在连线时一起完成。具体方法是:用连线工具在某个功能函数或 VI 的连线端子上单击鼠标右键,再从弹出的菜单中选择 Create Constant,就可以创建一个 具有正确的数据格式 的数值常数对象。
9,选择 File?Save,把该 VI 保存为 LabVIEW\ Activity 目录中的 Temp & Vol.vi。
在前面板中,单击 Run(运行) 按钮,运行该 VI。注意电压和温度的数值都显示在前面板中。
10.选择 File?Close,关闭该 VI 。
练习 1 -1 结束
附注与说明,
1.如果要查看某个功能函数或者 VI 的输入输出,需要从
Help菜单中选择 Show Help,再把光标置于这个功能函数或者 VI
上。例如进程监视器 VI 的 Help 窗口显示如下,
2.显示对象( Indicator),控制对象( Control)和数值常数对象
显示对象和控制对象都是前面板上的控件,前者有输入端子而无输出端子,后者正好相反,它们分别相当于普通编程语言中的输出参数和输入参数。数值常数对象可以看成是控制对象的一个特例。
在前面板中创建新的控制对象或显示对象时,
LabVIEW 都会在流程图中创建对应的端子。端子的符号反映该对象的数据类型。例如,DBL 符号表示对象数据类型是双精度数; TF 符号表示布尔数; I16
符号表示 16 位整型数; ABC 符号表示对象数据类型是字符串。
一个对象应当是显示对象还是控制对象必须弄清楚,否则无法正确连线。有时他们的图标是相似或相同的,可以根据需要明确规定它是显示对象还是控制对象。方法是将鼠标移到图标上,然后点右键,可出现快速菜单(例见右图)。如果菜单中的第一项是
Chang to Control,说明这是一个显示对象,你可以根据需要,将其变为控制对象。如果菜单中的第一项是 Chang to Indicator,
说明这是一个控制对象,你也可以根据需要,将其变为显示对象。
控制对象和显示对象都不能在流程图中删除,只能从前面板上删除。
3.关于连线
连线是程序设计中较为复杂的问题。流程图上的每一个对象都带有自己的连线端子,连线将构成对象之间的数据通道。因为这不是几何意义上的连线,因此并非任意两个端子间都可连线,连线类似于普通程序中的变量。数据单向流动,从源端口向一个或多个目的端口流动。不同的线型代表不同的数据类型。下面是一些常用数据类型所对应的线型和颜色,
类型 颜色 标量 一维数组 二维数组
整形数 兰色
浮点数 橙色
逻辑量 绿色
字符串 粉色
文件路径 青色
当需要连接两个端点时,在第一个端点上点击连线工具(从工具模板栏调用),然后移动到另一个端点,再点击第二个端点。端点的先后次序不影响数据流动的方向。
当把连线工具放在端点上时,该端点区域将会闪烁,表示连线将会接通该端点。当把连线工具从一个端口接到另一个端口时,不需要按住鼠标键。当需要连线转弯时,点击一次鼠标键,即可以正交垂直方向地弯曲连线,按空格键可以改变转角的方向。
接线头是为了帮助正确连接端口的连线。当把连线工具放到端口上,接线头就会弹出。
接线头还有一个黄色小标识框,显示该端口的名字。
线型为波折号的连线表示坏线。出现坏线的原因有很多,例如:连接了两个控制对象;
源端子和终点端子的数据类型不匹配(例如一个是数字型,而另一个是布尔型) 。可以通过使用定位工具点击坏线再按下 <Delete> 来删除它。选择 Edit?Remove Bad Wires 或者按下 <Ctrl-B> 可以一次删除流程图中的所有坏线。当 VI 无法运行,或者显示 Signal has
Loose Ends (信号丢失终端)的错误信息时,这是一个快捷的调试方法。
1.4.2 程序调试技术
1.找出语法错误
如果一个 VI程序存在语法错误,则在面板工具条上的运行按钮会变成一个折断的箭头,
表示程序不能被执行。 这时该按钮被称作错误列表。 点击它,则 LabVIEW 弹出错误清单窗口,
点击其中任何一个所列出的错误,选用 Find 功能,则出错的对象或端口就会变成高亮。
2.设置执行程序高亮
在 LabVIEW 的工具条上有一个画着灯泡的按钮,这个按钮叫做“高亮执行”按钮上。
点击这个按钮使它变成高亮形式,再点击运行按钮,VI 程序就以较慢的速度运行,没有被执行的代码灰色显示,执行后的代码高亮显示,并显示数据流线上的数据值。这样,你就可以根据数据的流动状态跟踪程序的执行。
3.断点与单步执行
为了查找程序中的逻辑错误,有时希望流程图程序一个节点一个节点地执行。使用断点工具可以在程序的某一地点中止程序执行,用探针或者单步方式查看数据。使用断点工具时,点击你希望设置或者清除断点的地方。断点的显示对于节点或者图框表示为红框,对于连线表示为红点。当 VI 程序运行到断点被设置处,程序被暂停在将要执行的节点,以闪烁表示。按下单步执行按钮,闪烁的节点被执行,下一个将要执行的节点变为闪烁,指示它将被执行。你也可以点击暂停按钮,这样程序将连续执行直到下一个断点。
4.探针
可用探针工具来查看当流程图程序流经某一根连接线时的数据值。从 Tools 工具模板选择探针工具,再用鼠标左建点击你希望放置探针的连接线。这时显示器上会出现一个探针显示窗口。该窗口总是被显示在前面板窗口或流程图窗口的上面。在流程图中使用选择工具或连线工具,在连线上点击鼠标右键,在连线的弹出式菜单中选择“探针”命令,同样可以为该连线加上一个探针。
1.4.3 子 VI 的建立
子 VI( SubVI)相当于普通编程语言中的子程序,也就是被其他的 VI 调用的 VI。可以将任何一个定义了图标和联接器的 VI 作为另一个 VI 的子程序。在流程图中打开
Functions?Select a VI….,就可以选择要调用的子 VI 。构造一个子 VI 主要的工作就是定义它的 图标和联接器 。
每个 VI 在前面板和流程图窗口的右上角都显示了一个默认的图标。启动图标编辑器的方法是,用鼠标右键单击面板窗口的右上角的默认图标,在弹出菜单中选择 Edit Icon。
下图显示了图标编辑器的窗口。 可以用窗口左边的各种工具设计像素编辑区中的图标形状。编辑区右侧的一个方框中显示了一个实际大小的图标。图标编辑器的具体使用细节参阅有关资料。
图1-5 图标编辑器窗口
联接器是 VI 数据的输入输出接口。如果用面板控制对象或者显示对象从子 VI 中输出或者输入数据,那么这些对象都需要在联接器面板中有一个连线端子。您可以通过选择
VI 的端子数并为每个端子指定对应的前面板对象以定义联接器。
定义联接器的方法是,用鼠标右键单击面板窗口中的图标窗口,在快捷菜单中选择
Show Connector。
联接器图标会取代面板窗口右上角的图标。 LabVIEW 自动选择的端子连接模式是控制对象的端子位于联接器窗口的左边,显示对象的端子位于联接器窗口右边。选择的端子数取决于前面板中控制对象和显示对象的个数。
联接器中的各个矩形表示各个端子所在的区域,可以用它们从 VI 中输入或者输出数据。如果必要,也可以选择另外一种端子连接模式。方法是在图标上单击鼠标右键单出快捷菜单,选择 Show Connector,再次弹出快捷菜单,选择 Patterns。下面我们通过一个练习说明具体操作。
练习 1 -2 为 VI 创建图标和联接器
1.打开 LabVIEW\Activity 目录中的 Temp & Vol.vi,这是练习1-1做的程序。
2.在前面板中,用鼠标右键单击窗口右上角的图标,在快捷菜单中选择 Edit Icon….,
也可以双击图标激活图标编辑器。注意只能在前面板中编辑图标和联接器。
3.删除默认图标。使用 Select Tool(矩形框),单击并拖动想要删除的部分,按下
<Delete>。也可以通过双击工具框中的阴影矩形删除图标。
4.用 Pencil Tool (铅笔工具)绘制一个温度计。
5.用 Text Tool(文本工具)创建文本。得到图标将如下图所示。
图1-6 编辑后的图标编辑器窗口
6.单击 OK,关闭编辑器。新创建的图标就显示在屏幕右上角的图标窗口中。
7.用鼠标右键单击前面板中的图标窗口,在快捷菜单中选择 Show
Connector,设置联接器端子连接模式。在默认情况下,LabVIEW 会根据前面板中的控制对象和显示对象的数目确定联接器的端子连接模式。因为前面板中有两个对象,所以联接器有两个端子,如左图所示。用鼠标右键单击联接器窗口,在快捷菜单中选择 Rotate 90
Degrees(旋转 90 度),注意联接器窗口的变化,如左图所示。
9.将端子连接到温度计和电压计,
a,点击联接器上部端子。光标自动变成连线工具,同时端子变成黑色。
b,单击温度显示对象。一个移动的虚线框把它包围起来,选中的端子的颜色变为与控制 /显示对象的数据类型一致的颜色。
如果单击前面板中的任何空白区域以后,虚线消失,选中的端子变暗,这表示您已经成功地把显示对象和上部端子连接起来。如果端子是白色,则表示没有连接成功。
c,重复步骤 a 和 b,把底部的端子和容积计连接起来。
d,用鼠标右键单击联接器,在快捷菜单中选择 Show Icon…,
10.选择 File?Save,保存该 VI。
这样这个 VI 就完成了,并也可以作为子 VI 被其他的 VI
调用。子 VI 的图标在主 VI 的流程图中代表它。 VI 的联接器
(含有两个端子)输出温度和电压。
练习 1 -2 结束
1.5 图表( chart)入门
图表( chart)是一种周期性更新数据的数字式图形显示对象。可以在
Controls?Graph 模板中找到两种图表:波形图和强度图
(后者不常用)。也可以自定义图表的格式,以满足自己的显示需要或者让它显示更多的数据。图表具有的特性有:
滚动条、图例、模板、数值显示、时间坐标显示。
右图显示了快速菜单中
Advanced?Update Mode 子菜单中提供的三种图表显示类型—— Strip chart(条状图),
Scope chart(示波器图)和 Sweep chart(扫描图)。默认模式是条状图。
练习 1-3 使用三种图表模式
目的:查看 VI 分别在三种模式下执行时图表的显示。
1.建立前面板及流程图如下
该程序中利用一个循环产生连续的 sin(i)函数值,并及时地在 chart 图表上显示出来,现在前面板上的 chart 是一个 strip,这是一个坐标式显示器,与纸带式图表记录器相似。每接受一个新数据,新数据就将显示在右侧,而原有数据移动到左侧
10
sin(x)
stop
100
图1-7 图表的例子
2.用鼠标选中 chart,点击右键,可在快速菜单中选择 Advanced?Update Mode 子菜单。
可以选择更换其他两种更新模式。
示波器模式是一个返回式的显示器,与示波器类似。每接受一个新数据时,它就把新数据绘制在原有数据的右侧。当数据曲线到达显示区的右边缘时,VI 会删除全部图形,从左边缘重新开始绘制曲线。示波器模式显然要快于条状图模式,因为它不会因为滚动产生溢出。
扫描模式更接近于示波器模式,但是当数据曲线到达显示区的右边时,不会变成空白,而是会出现一个移动的垂线,标记新数据的开始,并当 VI 添加新数据时穿过整个显示区。
练习 1-3 结束。
重叠式和堆栈式图区
LabVIEW 可以用同一个垂直坐标在一个图表中显示多个图区,这种图区被称为重叠式图区,也可使用多个垂直坐标,这时这种图形被称为堆栈式图区。请参考 Examples\ General\
Graphs\ charts.llb 中的 charts.vi 示例。
补充练习,
通过下面的要求练习 LabVIEW 的操作。
画出如右下所示的流程图,配以适当的前面板。注意连线时快捷菜单和 Create 功能的使用,和在前面板上替换不同的 Indicator 的方法。
3.14
cos(x)
sin(x)
图1-8 补充练习的面板及框图
第二章 程序结构
2.1 循环结构
2.1.1 While 循环
While 循环可以反复执行 循 环体的程序,直至到达某个边界条件。它类似于普通编程语言中的 Do 循环和 Repeat-Until 循环。 While 循环的框图是一个大小可变的方框,用于执行框中的程序,直到条件端子接收到的布尔值为 FALSE。
null 该循环有如下特点,
null 计数从 0 开始( i=0)。
null 先执行循环体,而后 i+1,如果循环只执行一次,那么循环输出值 i=0。
null 循环至少要运行一次。
循环变量条件端子
图2-1 While 循环示意图
练习 2-1 使用 While 循环和图表
目的:用 While 循环和图表获得数据,并实时显示。
创建一个可以产生并在图表中显示随机数的 VI。 前面板有一个控制旋钮可在 0 到 10 秒之间调节循环时间,还有一个开关可以中止 VI 的运行。学习怎样改变开关的动作属性,以便不用每次运行 VI 时都要打开开关。操作步骤如下,
前面板
控制开关
1.0
0.0
0.2
0.4
0.6
0.8
10230
随机信号
10.0
0.0
2.0
4.0 6.0
8.0
循环延时
ON
OFF
图2-2 练习2-1的前面板
1,选择 File?New,打开一个新的前面板。
2,选择 Controls?Boolean,在前面板中放置一个开关。
设置开关的标签为控制开关。
3,使用标签工具创建 ON 和 OFF 的标签,放置于开关旁。
4,选中 Controls?Graph,在前面板中放置一个波形图 (是
chart,而不是 graph)。设置它的标签为随机信号。这个图表用于实时显示随机数。
5,把图表的纵坐标改为 0.0 到 1.0。方法是用标签工具把最大值从 10.0 改为 1.0。
6,选择 Controls?Numeric,在前面板中放置一个旋钮。
设置旋钮的标签为循环延时。这个旋钮用于控制 While 循环的循环时间。
流程图
7,开流程图,按照下图创建流程图。
随机信号循环延时控制开关
图2-2 练习2-1的流程图
a,从 Functions?Structures 中选择 While 循环,把它放置在流程图中。 将其拖至适当大小,将相关对象移到循环圈内。
b,从 Functions? Numeric 中选择随机数( 0-1)功能函数放到循环内。
c,在循环中设置 Wait Until Next ms Multiple 函数
( Functions?Time & Dialog),该函数的时间单位是毫秒,按目前面板旋钮的标度,可将每次执行时间延迟 0 到 10 毫秒。
d,照上面所示的流程图连线,把随机数功能函数和随机信号图表输入端子连接起来,并把启动开关和 While 循环的条件端子连接。
8,返回前面板,调用操作工具后单击垂直开关将它打开。
9,把该 VI 保存为 LabVIEW\ Activity 目录中的 Random
Signal.vi。
10,执行该 VI。 While 循环的执行次数是不确定的,只要设置的条件为真,循环程序就会持续运行。在这个例子中,只要开关打开( TRUE),框图程序就会一直产生随机数,并将其在图表中显示。
11,单击垂直开关,中止该 VI。关闭开关这个动作会给循环条件端子发送一个 FALSE 值,从而中止循环。
12,用鼠标右键单击图表,选择 Data Operations?Clear
Chart,清除显示缓存,重新设置图表。
练习 2-1结束
附注与说明
布尔开关的机械动作,
布尔开关有 6 种机械动作属性可供选择。在前面板上用鼠标右键单击开关,在快捷菜单中选择 Mechanical Action 就可以看到这些可选的动作。 LabVIEW 还提供了一个范例示范这些动作,它是位于 Examples\ General\ Controls\ booleans.llb 的 Mechanical Action of
Booleans.vi。
2.1.2 移位寄存器( Shift Register)
移位寄存器可以将数据从一个循环周期传递到另外一个周期。在程序设计中,经常要用到它.创建一个移位寄存器的方法是,用鼠标右键单击循环的左 边或者右 边,在快捷菜单中选择 Add Shift Register。如右图所示。
移位寄存器在流程图上用在循环边框上相应的一对端子来表示。右边的端子中存储了一个周期完成后的数据,这些数据在这个周期完成之后将被转移到左边的端子,赋给下一个周期。移位寄存器可以转移各种类型的数据--数值、布尔数、数组、字符串等等。它会自动适应与它连接的第一个对象的数据类型。下图表示了它的工作过程,
图2-3 Shift Register 的工作过程
可以令移位寄存器记忆前面的多个周期的数值。 这个功能对于计算数据均值非常有用。 还可以创建其他的端子访问先前的周期的数据,方法是用鼠标右键单击左边或者右边的端子,在快捷菜单中选择 Add Element。例如,如果某个移位寄存器左边的端口含有三个元素,那么就可以访问前三个周期的数据。
练习 2-2 使用移位寄存器
目的:创建一个可以在图表中显示运行平均数的 VI。
前面板
1.打开一个新的前面板,按照下图所示创建对象。
2.把波形图表的坐标范围改为 0.0 到 2.0。
3.在添加竖直坐标之后,用鼠标右键单击它,在快捷菜单中选择 Mechanical
Action?Latch When Pressed,再 选 择 Operate?Make Current Values Default,把 ON 状态设置为默认状态。
2.0
0.0
0.5
1.0
1.5
500
随机数
Boolean
ON
OFF
缺省值,ON
机械动作
Latch When
Pressed
图2-4 练习2-2的前面板
流程图
4.按下图创建流程图。
0.5
随机数
4.00
500
Boolean
图2-4 练习2-2的流程图
5.在流程图中添加 While 循环 (Functions?Structures),创建移位寄存器。
a,用鼠标右键单击 While 循环的左边或者右边,在快捷菜单中选择 Add Shift Register。
b,用鼠标右键单击寄存器的左端子,在快捷菜单中选择 Add Element,添加一个寄存器。用同样的方法创建第三个元素。
6,Random Number (0–1)函数( Functions?Numeric)——产生 0 到 1 之间的某个随机数。
7,Compound Arithmetic 函数( Functions?Numeric)——在本练习中,它将返回两个周期产生的随机数的和。如果要加入其他的输入,只需用右键单击某个输入,从快捷菜单中选择 Add Input。
8.除法函数( Functions?Numeric)——在本练习中,它用于返回最近四个随机数的平均值。
9.数值常数( Functions?Numeric)——在 While 循环的每个周期,Random Number (0–1)
函数将产生一个随机数。 VI 就将把这个数加入到存储在寄存器中的最近三个数值中。
Random Number (0–1)再将结果除以 4,就能得到这些数的平均值(当前数加上以前的三个数) 。然后再将这个平均值显示在波形图中。
10,Wait Until Next ms Multiple 函数 ( Functions?Time & Dialog)——它将确保循环的每个周期不会比毫秒输入快。在本练习中,毫秒输入的值是 500 毫秒。如果用鼠标右键单击图标,从快捷菜单中选择 Visible?Label,就可以看到 Wait Until Next ms Multiple
的标签。
11,用鼠标右键单击 Wait Until Next ms Multiple 功能函数的输入端子,在快捷菜单中选择 Create Constant。出现一个数值常数,并自动与功能函数连接。
12,将 Constant 设置为 500。这样连接到函数的数值常数设置了 500 毫秒的等待时间。
因此循环每半秒执行一次。注意,VI 用一个随机数作为移位寄存器的初始值。如果没有设置移位寄存器端子的初始值,它就含有一个默认的数值,或者上次运行结束时的数值,因此开始得到的平均数没有任何意义。
13,执行该 VI,观察过程。
14,把该 VI 保存为 LabVIEW\Activity 目录下的 Random Average.vi。
练习 2-2 结束。
附注:移位寄存器的初值,
上面的练习中对移位寄存器设置了初值 0.5。如果不 设这个初值,默认的初值是0。
在这个例子中,一开始的计算结果是不对的,只有到循环完3次后移位寄存器中的过去值才填满,即第4次循环执行后可以得到正确的结果。
2.1.3 For 循环
For循环用于将某段程序执行指定次数。 和 While 循环一样,
它不会立刻出现在流程图中,而是出现一个小的图标,而后您可以修改它的大小和位置。具体的方法是,先单击所有端子的左上方,然后按下鼠标,拖曳出一个包含所有端子的矩形。释放鼠标时就创建了一个指定大小和位置的 For 循环。
100
图表
For 循环将把它的框图中的程序执行指定的次数,For 循环具有下面这两个端子,
N,计数端子(输入端子)——用于指定循环执行的次数。
I,周期端子(输出端子)——含有循环已经执行的次数。
上图显示了一可以产生 100 个随机数并将数据显示在一个图表上的 For 循环。在该例中,i 的初值是 0,终值是 99。
练习 2-3 使用 For 循环
目的:用 For 循环和移位寄存器计算一组随机数的最大值。
1,打开一个新的前面板,按照下图创建对象。
a,将一个数字显示对象放在前面板,设置它的标签为,最大值”。
b,将一个波形图表放在前面板,设置它的标签为“随机数”。将图表的纵坐标范围改为 0.0 到 1.0。
c,在图表的快捷菜单中选择 Visible Items?Scrollbar
和 Digital Display,并隐藏 Plot Legend。
d,用移位工具修改滚动栏的大小。
100
0
随机数最大值图2- 5 练习2- 3 的面板和流程图
2,按照上图画流程图。
3.在流程图中放置一个 For 循环
( Functions?Structures)。
4.在 For 循环的边框处单击鼠标右键,在快捷菜单中选择
Add Shift Register。
5.将下列对象添加到流程图。
a Random Number (0– 1)函数( Functions?Numeric)—
—产生 0 到 1 之间的某个随机数。
b 数值常数( Functions?Numeric)——在这个练习中需要将移位寄存器的初始值设成 0。
c Max&Min 函数( Functions?Comparison)——输入两个数值,再将它们的最大值输出到右上角,最小值输出到右下角。
这里只需要最大值,只用连接最大值输出。
d 数值常数( Functions?Numeric)—— For 循环需要知道需要执行的次数。本练习中是 100 次。
6.按照上图连接各个端子。
7.运行该 VI。
8.将该 VI 保存为 LabVIEW\ Activity 目录下的 Calculate
Max.vi。
练习 2-3 结束。
2.2 分支结构,Case
Case 结构含有两个或者更多的子程序( Case),执行那一个取决于与选择端子或者选择对象的外部接口相连接的某个整数、
布尔数、字符串或者标识的值。必须选择一个默认的 Case 以处理超出范围的数值,或者直接列出所有可能的输入数值。 Case
结构见下图,各个子程序占有各自的流程框,在其上沿中央有相应的子程序标识,Ture,False 或1、2、3…。按钮用来改变当前显示的子程序(各子程序是重叠放在屏幕同一位置上的)。
False
练习 2 -4 使用 Case 结构
子程序标识按钮条件端子
目的:创建一个 VI以检查一个数值是否为正数。如果它是正的,VI就计算它的平方根,反之则显示出错。
前面板
1,打开一个新的前面板,并按照下图所示创建对象。控制对象用于输入数值,显示对象用于显示该数值的平方根。
流程图
2,照下图创建流程图。
2.00
Number
1.41
SQRT
SQRT
Number
True
SQRT
Number
-999.00
Errot...
False
图2-6 练习2-4的面板和流程图
3,从 Functions?Structures 中选择一个 Case 结构,并放置在在流程图中。 Case 结构是一个可以改变大小的方框。先来做 Ture 的情况,照流程图上半部分构造。
a Greater Or Equal To 0? 函数 ( Functions?Comparison)
——如果输入数值大于或者等于 0 就会返回一个 TRUE 值。
b Square Root 函数( Functions?Numeric)——返回输入数值的平方根。
c 连好线
d 点击 Case 框的选择按钮,转入 False 情况编程
e 数值常数( Functions?Numeric)——这里用于显示错误的代数值 -999.00。
f One Button Dialog 函数( Functions?Time &
Dialog)——在这里它用于显示一个对话框,内容是
Error...。
g 字符串常数 (Functions?String)——用 Edit Text
A
D
C
B
Tools 在对话框中输入字符串。
h 该 VI 在 TRUE 或者 FALSE 情况下都会执行。如果输入的数值大于等于 0,VI 会执行 TRUE Case,返回该数的平方根,
否则将会输出- 999.00,并显示一个对话框,内容为 Error...。
4,返回前面板,运行该 VI。修改标签为 Number 的数字式控制对象的数值,分别尝试一个正数和负数。注意,当把数字式控制对象的值改为负数时,LabVIEW 会显示 Case 结构的 FALSE
Case 中设置的出错信息。
5,保存该 VI 到 LabVIEW\ Activity 目录中的 Square
Root.vi。
VI 的算法
本练习中的流程图功能相当于代码式编程语言中的下列伪代码,
if (Number >= 0) then
Square Root Value = SQRT(Number)
else
Square Root Value = -999.00
Display Message "Error.,"
end if
练习 2 -4 结束。
2.3 顺序结构和公式节点
2.3.1 顺序结构( Sequence Structure)
在代码式的传统编程语言中,默认的情况是,程序语句按照排列顺序执行,但 LabVIEW
中不同,它是一种图形化的数据流式编程语言。在图2-7左图中,假设有 A,B,C,D4
个节点,其数据流向如右图所示。按照数据流式语言的约定,任何一个节点只有在所有
图2-7 顺序结构的说明
的输入数据有效时才会执行,所以图中,当且仅当 A,B,C3个节点执行完,使得 D 节点的
3个输入数据都到达 D 节点后,D 节点才执行。但是你要注意,这里并没有规定 A,B,C3
个节点的执行顺序。在 LabVIEW 中这种情况下,A,B,C 的执行顺序是不确定的,如果你需要对它们规定一个确定的顺序,那就需要使用本节介绍的“顺序结构” 。
图2-7中的右边是顺序结构的图标,它看上去像是电影胶片。它可以按一定顺序执行多个子程序。首先执行 0 帧中的程序,然后执行 1 帧中的程序,逐个执行下去。与 Case 结构类似,这多帧程序在流程图中占有同一个位置。
练习 2 -5 使用顺序结构
目的:创建一个 VI,计算生成等于某个给定值的随机数所需要的时间。
前面板
1,打开一个新的前面板,并按照下图所示创建对象。
50
给定数据
50
当前值
6
执行次数
0.00
匹配时间(秒)
图2-8 练习2-5的前面板
我们约定数据是0到 100 范围的整数。 当前值用于显示当前产生的随机数。,执行次数”
用于显示达到指定值循环执行的次数。匹配时间用来显示达到指定值所用的时间。
流程图
读取初始时间
0 [0..2]
100.00
给定数据当前值执行次数匹配计算
1 [0..2]
1000.00
匹配时间(秒)
计算延时时间(秒)
2 [0..2]
图2-8 练习2-5的流程图(共3帧)
1,在流程图中放置顺序结构 (Functions?Structures)。
2,用鼠标右键单击帧的边框,在快捷菜单中选择 Add
Frame After,创建一个新帧。重复这个步骤,再创建一个帧。
共3桢。
3,选中第0桢,设置读取初始时间(子)程序
4,第 0 帧的下边框上含有一个小方框,其中有一个箭头。
这个方框叫做顺序局部变量,可以在同一个顺序结构中的各个帧之间传递数据。用鼠标右键单击第 0 帧的底部边框,选择 Add
Sequence Local,创建顺序局部变量。顺序局部变量显示为一个空的方块。当您将某个功能函数与顺序局部变量相连时,方块中的箭头就会自动显示。
5,Tick Count (ms) 函数( Functions?Time &
Dialog)——返回启动到现在的时间(以毫秒为单位)。
在这里例子里需要使用两个这个函数。另一个在第2帧中。
6,按图连好线。转入第1帧。该帧是匹配计算,内含一个循环结构。该图中使用的新函数有,
Round to Nearest 函数( Functions?Numeric)——在该例中,它用于取 0 到 100 之间的随机数到距离最近的整数。
Not Equal?函数( Functions? Comparison)——在该例中,它将随机数和前面板中设置的数相比较,如果两者不相等会返回 TRUE 值,否则返回 FALSE。
Increment 函数( Functions?Numeric)——在该例中,
它将 While 循环的计数器加 1。
7,按图连好线。转入第2帧
在第 0 帧中,Tick Count ( ms)功能函数将以毫秒为单位表示当前时间。这个数值被连到顺序局部变量,这样它就可以被后续的帧使用。在第 1 帧中,只要函数返回的值与指定值不等,
VI 就会持续执行 While 循环。在第 2 帧中,Tick Count ( ms)
功能函数以毫秒为单位返回新的时间。 VI 从中减去原来的时间
(由第 0 帧通过顺序局部变量提供)就可以计算出花费的时间。
8,返回前面板,在 Number to Match 控制对象中输入一个数值,执行该 VI。
9,把该 VI 保存为 LabVIEW\ Activity 目录下 Time to
Match.vi。
练习 2-5 结束。
附注与说明,设置数据范围
在设定一个数据对象时,可以设置对输入数据的限制,利用快捷键选择 Data Range… 选项,将会出现如下对话框,
图2-9 设置数据范围
它可以防止用户创建的控制对象或显示对象的值超出某个预设的范围。 您可以选择忽略这个值,将它强制修改到范围以内,
或暂停程序的执行。在程序执行时,如果发生溢出错误,溢出错误符号将显示在工具栏中的执行按钮的位置。而且,一个立体的黑框将把发生溢出的控制对象包围起来。
2.3.2 公式节点( Formula Node)
公式节点是一个大小可变的方框,可以利用它直接在流程图中输入公式。从 Functions?Structures 中选择公式节点就可以把它放到流程图中。当某个等式有很多变量或者非常复杂时,这个功能就非常有用。例如等式,y = x
2
+ x + 1 使用公式节点可以表示为,
图2-10 公式节点示意图
利用公式节点可以直接输入一个或者多个复杂的公式,而不用创建流程图的很多子程序。使用文本编辑工具来输入公式。创建公式节点的输入和输出端子的方法是,用鼠标右键单击第 0
帧的底部边框,选择 Add Input (Add Output)。再在节点框中输入变量名称。变量名对大小写敏感。然后就可以在框中输入公式。每个公式语句都必须以分号( ;)结尾。
公式节点的帮助窗口中列出了可供公式节点使用的操作符、
函数和语法规定。一般说来,它与 C 语言非常相似,大体上一个用 C 写的独立的程序块都可能用到公式节点中。 但是仍然建议不要在一个公式节点中写过于复杂的代码程序。
下面这个例子显示了如何在一个公式节点中执行不同条件时的数据发送。
请阅读下面这段程序代码,如果 X 为正数,它将算出 X 的平方根并把该值赋给 Y,如果 X 为负数,程序就给 Y 赋值 -99。
if (x >= 0) then
y = sqrt(x)
else
y = -99
end if
可以用公式节点取代上面这段代码,如下图所示,
output
input Y=(X>=0)?sqrt(X):-99;
Y
X
注意:公式节点中变量字母 X,Y 大、小写是有区别的,开方的函数 sqrt(X)中函数名称是小写。
练习 2-6 使用公式节点
目的:创建一个 VI,它用公式节点计算下列等式,
y1 = x
3
– x
2
+ 5
y2 = m* x + b
x 的范围是从 0 到 10。 可以对这两个公式使用同一个公式节点,并在同一个图表中显示结果。
前面板
30.00
m
20.00
b
1000.0
0.0
200.0
400.0
600.0
800.0
100 1 2 3 4 5 6 7 8 9
y1
y2
Waveform Graph
图2-11 练习2-6的面板
1,打开一个新的前面板,按照上图(该图中包含运行结果) 创建前面板中的对象。 波形图显示对象用于显示等式的图形。
该 VI 使用两个数字式控制对象来输入 m 和 b 的值。
流程图
2,按照下图创建流程图。
图2-12 练习2-6的流程图
在创建某个输入或者输出端子时,必须给它指定一个变量名。这个变量名必须与公式节点中使用的变量名完全相符。
公式节点中,在边框上单击鼠标右键,在快捷菜单中选择
Add Input,可以创建三个输入端子。在快捷菜单中选择 Add
Output,创建输出端子。
x 的范围是从 0 到 10(包括 10),就必须连接 11 到计数端子。
Build Array ( Functions?Array)——在这个例子中,它用于将两个数据构成数组形式提供给一个多曲线的图形中。通过用变形工具拖拉边角就可以创建两个输入端子。
11
y1=x**3+x**2+5;
y2=m*x+b;
y2
x
b
y1
m
m
Formule Node
b
Waveform Graph
3,返回前面板,尝试给 m和 b赋以不同的值再执行该 VI。
4,把该 VI 保存为 LabVIEW/Activity 目录下的
Equations.vi。
练习 2-6 结束。
第三章 数据类型:数组、簇和波形
3.1 概述
数组是同类型元素的集合。一个数组可以是一维或者多维,
如果必要,每维最多可有 2
31
- 1 个元素。可以通过数组索引访问其中的每个元素。索引的范围是 0 到 n – 1,其中 n 是数组中元素的个数。图3-1所显示的是由数值构成的一维数组。注意第一个元素的索引号为 0,第二个是 1,依此类推。数组的元素可以是数据、字符串等,但所有元素的数据类型必须一致。
图3-1 数组示意图
簇( Cluster)是另一种数据类型,它的 元素可以是不同类型的数据。它类似于 C 语言中的 stuct。使用簇可以把分布在流程图中各个位置的数据元素组合起来,这样可以减少连线的拥挤程度。减少子 VI 的连接端子的数量。
波形( Waveform)可以理解为一种簇的变形,它不能算是一种有普遍意义的数据类型,
但非常实用。
3.2 数组的创建及自动索引
3.2.1 创建数组
一般说来,创建一个数组有两件事要做,首先要建一个数组的“壳” ( shell),然后在这个壳中置入数组元素(数或字符串等) 。
如果需要用一个数组作为程序的数据源,可以选择
Functions?Array?Array Constant,将它放置在流程图中。然后再在数组框中放置数值常量、布尔数还是字符串常量。下图显示了在数组框放入字符串常量数组的例子。左边是一个数组壳,中间的图上已经置入了字符串元素,右边的图反映了数组的第0个元素为:,ABC”,后两个元素均为空。
ABC
0
Array Constant
ABC
0
Array Constant
0
Array Constant
图3-1 数组的创建
在前面板中创建数组的方法是,从 Controls 模板中选择
Array & Cluster,把数组放置在前面板中,然后选择一个对象
(例如数值常量) 插入到数组框中。 这样就创建了一个数值数组。
也可以直接在前面板中创建数组和相应的控制对象,然后将它们复制或者拖曳到流程图中,创建对应的常数。
还有很多在流程图中创建和初始化数组的方法,有些功能函数也可以生成数组。
3.2.2 数组控制对象、常数对象和显示对象
通过把数组与数值、布尔数、字符串或者簇组合在一起,可以在前面板和流程图中创建任何一种控制对象、常数对象和显示对象。数组元素不能是数组、图表或者图形。如果您想查看一些数组的例子,请查看 Examples\ General\ arrays.llb 中的例子。
3.2.3 自动索引
For 循环和 While 循环可以自动地在数组的上下限范围内编索引和进行累计。这些功能称为自动索引。在启动自动索引功能以后,当把某个外部节点的任何一维元素连接到循环边框的某个输入通道时,该数组的各个元素就将按顺序一个一个地输入到循环中。循环会对一维数组中的标量元素,或者二维数组中的一维数组等编制索引。在输出通道也要执行同样的工作――数组元素按顺序进入一维数组,一维数组进入二维数组,依此类推。
在默认情况下,对于每个连接到 For 循环的数组都会执行自动索引功能。可以禁止这个功能的执行,方法是用鼠标右键单击通道(输入数组进入循环的位置),在快捷菜单中选择 Disable
Indexing。
练习 3-1 创建一个自动索引的数组
目的:使用 For 循环的自动索引功能创建数组,并用一个图形( Graph)显示该数组。
前面板
图3-2 练习3-1的面板
2,打开一个新的前面板。
3,选择 Controls?Array & Cluster,在前面板中放置一个数组。设置它的标签为 Waveform Array。
4,选择 Controls?Numeric,在数组框中插入一个数字式显示对象。如右图所示。它用于显示数组的内容。
5,选择 Controls?Graph,在前面板中放置一个波形图。
设置它的标签为 Waveform Graph。
6,隐藏图例和模板。
7,用鼠标右键单击图形,并在快捷菜单中取消选中 Y
Scale?Autoscale Y,禁止自动坐标功能。
8,使用文本工具,把 Y 轴的范围改为 -0.5 到 1.5。
流程图
9,按照下图创建流程图。
图3-2 练习3-1的流程图
null 由 Functions?Select a VI… 寻找
LabVIEW\ activity 目录下的 Generate Waveform
VI,它的作用是返回波形中的某一点。这个 VI
需要输入一个索引,我们将循环周期连接到这个输入。
null 注意 Generate Waveform VI 连出来的连线在循环边界变成一个数组时会变粗,正是在这个边界处形成了一维数组。
null For 循环会自动累计边界内的数组。 这种功能叫做自动索引。在这个例子中,连接到循环计数输入的数值常数令 For
循环创建了一个由 100 个元素组成的数组。
null Bundle 函数( Functions? Cluster)—
—将图块中的各个组件组合成一个簇,在正确连接以前需要改变该函数的图标的大小。将移位工具放在图标的左下角。变形工具会变成如左图所示,拖曳鼠标直到出现第三个输入端子。
null 数值常数( Functions?Numeric)——三个数值常数用于设置 For 循环执行的周期数 N=100,初始 X=0 和 delta X=1。
10,从前面板执行该 VI。 该 VI 将把自动索引后的波形图数组显示在波形图中。
11,把 X 的 delta 值改为 0.5,X 的初始值改为 20。再次执行该 VI。注意,波形图现在同样显示 100 个点,而每个点的初始值为 20,X 的 delta 值为 0.5(见 X 轴)。
12,只需在显示器中输入元素的索引号就可以查看波形数组中的任何元素。如果输入的数比数组的元素个数大,那么显示
X0Delta X
1 0
100
Waveform Graph
Waveform Array
器将变暗,表示您没有为该元素设置索引。
如果需要一次查看多个元素,可以通过改变数组显示对象的大小来实现。 把定位工具放置在数组框的右下角。工具将变成右图所示的变形工具。当工具变形时,用鼠标拖曳数组的右边或者下边。 数组现在就可以按照元素索引的上升顺序显示多个素,以某个与指定索引对应的元素开始,如下图所示。
图3-3 练习3-1中多个数组元素的同时观察
在前面的流程图中,您为波形图指定了初始的 X 值和 delta
X 值。默认的 X 初始值是 0,delta X 值是 1。这样,也可以把波形数组直接连接到波形图端子,而无需指定初始的 X 值和
delta X 值,如图3-4所示。
图3-4 练习3-1使用默认 X 及 Delta X 时简化后的流程图
13,按上图删除 Bundle 功能函数和它所连接的常数对象。
方法是用移位工具选择该功能函数和连接的常数对象,按下
<Delete>。再选择 Edit?Remove Bad Wires。按照上图完成流程图的连线。
14,执行该 VI。注意初始的 X 值是0,delta X 值是 1。
null 多图区图形
可以创建含有多条曲线的图形,方法是创建一个数组,用它来汇集传给单图区图形的类型的数据元素。
Build Array
0.5
100
50
Waveform Graph
Array
图3-5 练习3-1多图区图形的流程图
15,按照上图创建流程图。
null 正弦函数
( Functions?Numeric?Trigonometric)——在这里,它用于在 For 循环中创建一个由数据点组成的数组,表示一个正弦波周期。
null Pi 常数( Functions?Numeric?Additional
Numeric Constants)
null Build Array ( Functions?Array)——在这里,它用于创建合适的数据结构 (一个二维数组),
在波形图中绘制两条曲线。。用移位工具拖曳边角可以增大该函数的面积,创建两个输入端子。
16,返回前面板,执行该 VI。注意同一个波形中的两个图区。默认情况下,它们的 X 初始值都是 0,delta X 初始值都是
1。下图是该程序的运行结果(前面板未改动)。
17,把该 VI 保存为 LabVIEW\ Activity 目录中的 Graph
Waveform Arrays.vi。
18,可以修改图形中的某个图区的外观。方法是,用鼠标右键单击这个图形,再从弹出菜单选择对应的图例。
-0.09
0
Array
1.5
-0.5
0.0
0.5
1.0
1000 10 20 30 40 50 60 70 80 90
Plot 0
Waveform Graph
图3-6 练习3-1多图区图形的面板显示
练习 3-1 结束。
在上面这个例子中,由于计算端子连接了一个值为 100 的常数对象,所以 For 循环将执行 100 次。下面这个例子显示了另外一种控制循环执行次数的方法。
更详细的例子建议调阅 Examples,Fundamentals,Graphs
and Charts,Graph Examples,Waveform Graph 例子。
练习 3-2 对输入数组使用自动索引功能
目的:打开并执行一个 VI,它将在一个 For 循环中使用自动索引功能处理一个数组。
1,选择 File?Open…,打开
Examples\ General\ arrays.llb 中的 Separate Array Values
VI 。
2,打开流程图。下面的示意图显示的是在 TRUE 和 FALSE
时的情况。
0
0.0
Initialize
Array
Build Array
True
Negative Array
Positive Array
Input Array
0
0.0
Initialize
Array
Build Array
False
Negative Array
Positive Array
Input Array
图3-7 练习3-2的流程图
注意,Input Array 引出的连线与 For 循环外的粗线不同,
表示这是一个数组,而循环内部的细线则表示这是一个数组元素。 数组元素在每个循环期间将自动编号。
null 用自动索引功能设置 For 循环的计数器
注意,计数器端子还没有连线。当您对某个进入 For
循环的数组使用自动索引功能时,循环就将根据数组的大小执行相应的次数,这样就无需连接某个值到计数器的端口。如果对一个以上的数组使用自动索引功能,或者在使用自动索引功能之外还需要设置计数器时,实际的循环次数将是其中最小的数。
3,执行该 VI。在输入的八个数中,可以看到 4 个属于正数数组,另外 4 个属于负数数组。
4,从流程图中将一个值为 5 的常数对象连接到 For 循环的计数器端子。执行该 VI。可以看到尽管输入数组仍然有八个元素,但是 3 个位于正数数组,另外 2 个位于负数数组。 这说明,
如果设置了 N 并开启了自动索引功能,那么实际循环的次数将取较小的数。
5,关闭该 VI,不要保存任何修改。
注:练习 3-2的算法说明
下面是一段伪代码,解释上面的算法,假定输入数组为 A(已赋值),B(正数),C(负数)。 Sbr,Scr 分别是与 B 数组、
C 数组对应的右寄存器数组,Sbl,Scl 分别是与 B 数组,C 数组对应的左寄存器数组,size 运算为测数组实际大小,ins 运算为将一个数插入数组中最左边的空位。
B=0
初始化
C=0
K=size(A(.))
测 A数组大小
For i=0 to k-1
p=A(i)
取第 I个元素值
if p>=0 then
Ins p,Sbr
将 p值插入右寄存器
Else
Ins p,Scr
end if
Sbl=Sbr
右寄存器值送给左寄存器
Scl=Scr
Next i
B=Sbr
右寄存器值送到正数组
C=Scr
Print B
显示
Print C
End
练习 3-2 结束。
3.3 数组功能函数
LabVIEW 提供了很多用于操作数组的功能函数,位于
Functions?Array 中。 其中包括 Replace Array Element,,Search 1D
Array,Sort 1D Array,Reverse 1D Array 和 Multiply Array
Elements 等等。
null 创建数组—— Build Array 函数( Functions?Array),用于根据标量值或者其他的数组创建一个数组。
开始时,Build Array 函数具有一个标量输入端子。您可以根据需要向该功能函数中加入任意数量的输入,输入可以是标量或者数组。如果要添加其他的输入,用鼠标单击函数的左侧,在弹出菜单中选择 Add Element Input 或者 Add Array Input。还可以用变形工具来增大节点的面积(把移位工具放置在某个对象的边角就会变成变形光标) 。也可以使用变形光标或者选择 Remove Input 来删除输入。
下图显示了利用流程图中的常数对象的值创建和初始化数组的两种方法。左侧的方法是,将 5 个字符串常数放入一个一维字符串数组中。右侧的方法是,将三组数值常数放入三个一维数值数组,再将这三个数组组成一个二维数组。这样最后产生的是一个 3x3 的数组,
三列分别是 3,4,7; –1,6,2; 5,–2,8.。
还可以通过结合其他的含有标量元素的数组来创建数组。例如,假设有两个数组,三个标量元素,可把它们组成一个新的数组,顺序是:数组 1,标量 1,标量 2,数组 2,标量 3。
null 初始化数组( Initialize Array)——用于创建所有元素值都相等的数组。下图中,该功能函数创建了一个一维数组。
元素输入端子决定每个元素的数据类型和数值,维长度输入端子决定数组的长度,例如,
假设元素类型是长整型,值为 5,维长度为 100,那么创建的数组是一个一维的、由 100 个值为 5 的长整型元素组成的数组。也可以从前面板控制端子、流程图常数或者程序其他部分的计算结果得到输入。
创建和初始化一个多维数组的方法是,用鼠标右键单击函数的右下侧,在弹出菜单中选择 Add Dimension。还可以使用变形光标来增大初始化数组节点的面积,为每个增加的维添加一个维长度输入端子。也可以通过缩小节点的方法来删除维,即从函数的弹出菜单中选择
Remove Dimension,或者使用变形光标。下面的示意图显示了怎样初始化一个三维数组。
如果所有的维长度输入都是 0,该函数会创建一个具有指定数据类型和维数的空数组。
null 数组大小—— Array Size 函数,返回输入数组中的元素个数。
null 数组子集( Array Subset)——选取数组或者矩阵的某个部分。
该函数可以返回从某个指针开始的部分数组,并包括了长度元素。下图显示了一些数组子集的例子,注意,数组索引从 0 开始。
null 索引数组( Index Array)——用于访问数组中的某个元素。
下图显示了一个索引函数的例子,它用于访问数组中的第三个元素。注意,因为第一个元素的索引为 0,所以第三个元素的索引是 2。
将一个二维数组与 Index Array 函数相连,Index Array 就会含 2 个索引端子。将一个三维数组与 Index Array 函数相连,Index Array 就会含 3 个索引端子。余类推。可以使用的索引端的符号是一个黑方快,被禁止使用的索引端( Disable Indexing)是一个空心的小方框。
当给一个被禁止使用的索引端连接上一个 Constant 或 Control 是它会自动变为黑方快,即变为可以索引,相反原来一个可以使用的索引端上连接的 Constant 或 Control 被删去时,
索引端符号会自动变为空心的小方框,即变为禁止使用。
也可以按照任何维的组合提取子数组,下面的示意图显示了怎样从一个二维数组中提取一个一维的行或者列数组。
还可以从一个三维数组中提取一个二维数组,方法是禁止两个索引端子,或者通过禁止一个索引端子提取一个一维数组。下图显示了从三维数组提取数组的各种方法。
下面的规则对使用剪切数组进行了规定,
输出对象的维数必须等于被禁止的索引端口的数目。例如
0 个索引端口被禁止=标量元素
1 个索引端口被禁止=二维元素
2 个索引端口被禁止=三维元素
启动的端子所连接的数值必须指定输出元素。
这样,您就可以理解,上图中左下方的例子的作用是,利用 0 列和 3 行的所有元素产生一个一维数组,而右上方的例子的作用是利用第一帧中的所有元素产生一个二维数组。新的第 0 个元素是与原有元素最近的元素。
练习 3-3 使用创建数组功能函数
目的:使用创建数组函数,把一些元素和输出组织成一个更大的数组。
图3-8 练习3-3的面板和框图
1,按照图3-8创建一个前面板。
2,从 Controls?Numeric模板中选择一个数字控制对象放置在前面板中,设置它的标签为 scalar 1。
3,复制并粘贴该数字显示对象,创建两个新的对象,并分别设置它们的标签为 scalar 2 和 scalar 3。
4,创建一个数字控制对象的数组,设置它的标签为 array
1。 复制并粘贴它,创建一个新的数组,设置它的标签为 array 2。
5,在 array 1,scalar 1,scalar 2,scalar 3,array
2 中输入数值 1 到 9。
6,创建流程图。选择 Functions?Array,在流程图中放置一个 Build Array 功能函数。用定位工具增大函数额面积,以容纳 5 个输入。
7,把数组和标量与 Build Array 连接起来。创建输出的一维数组,它由 array 1,scalar 1,scalar 2,array 2,scalar
3 中的元素所组成,如图所示。
8,执行该 VI。可以看到 array 1,scalar 1,scalar 2、
scalar 3,array 2 中的数值出现在同一个一维数组中。
9,保存该 VI 为 LabVIEW\ Activity 目录下的 Build
Array.vi。
练习 3-3 结束 。
3.4 什么是多态化( Polymorphism)?
多态化是指一种函数功能,即可以协调不同格式、维数或者显示的输入数据。大多数 LabVIEW 的函数都是多态化的。例如,
图3-9给出了 Add 函数的一些多态化组合。
图3-9 多态化组合的例子
第一个组合中,两个标量相加,结果还是一个标量。第二个组合中,该标量与数组中的每个元素相加,结果是一个数组。数组是数据的集合。第三个组合中,一个数组的每个元素被加到另一个数组的对应元素中。您还可以使用其他的组合,例如数值簇或者簇数组。
可以把这些准则应用到其他的 G 语言函数或者数据类型。 G
语言函数对于各种情况都具有多态性功能。 有些函数接受数值和布尔输入,而有些函数接受其他任何数据格式的组合。如果您想了解更多关于多态化的知识,请参阅 Online
Reference?Function and VI Reference。
3.5 簇
3.5.1 创建簇控制和显示
在前面板上放置一个簇壳( Cluster shell)就创建了一个簇。
然后你可以将前面板上的任何对象放在簇中。例如数组,你也可以直接从 Control 工具板上直接拖取对象堆放到簇中。 一个簇中的对象必须全部是 Control,或全是 Indicator,不能在同一个簇中组合 Control 与 Indicator,因为簇本身的属性必须是其中之一。一个簇将是 Control 或 Indicator,取决于其内的第一个对象的状态。如果需要可以使用工具重置簇的大小。右图所示是一个含4个 Control 的簇。也可以在流程图上用类似的方法创建簇常数。
如果你要求簇严格地符合簇内对象的大小,可在簇的边界上弹出快速菜单选择自动定义大小( Autosizing)
簇的序( Order)
簇的元素有一个序,它与簇内元素的位置无关。簇内第一个元素的序为 0,第二个是 1,
等等。如果你删除了一个元素,序号将自动调整。如果你想将一个簇与另一个簇连接,这两个簇的序和类型必须同一。
如果想改变簇内元素的序,可在快速菜单中选择 ReOrder Controls In Claster,这时会出现一个窗口,在该窗口内可以修改序。
3.5.2 使用簇与子 VI 传递数据
一个 VI 的连接窗口最大有 28 个端子,如果你不希望使用全部 28 个端子传递数据,这既烦琐又易出错。通过把控制或显示对象捆绑成一个簇的方法,仅使用一个端子就可以实现该功能。
null 捆绑( Bundle)数据
Bundle 功能将分散的元件集合为一个新的簇,或允许你重置一个已有的簇中的元素。可以用位置工具拖曳其图标的右下角以增加输入端子的个数。最终簇的序是取决于被捆绑的输入的顺序。
右图中 Bundle 图标中部的 Claster 端子用于用新元素重置原簇中的元素。
null 分解( Unbundle)簇
Unbundle 功能是 Bundle 的逆过程,它将一个簇分解为若干分离的元件。如果你要对一个簇分解,就必须知道它的元素的个数。
LabVIEW 还提供一种可以根据元素的名字来捆绑或分解簇的方法,稍后介绍。
练习 3-4 簇
目的:学习创建簇、分解簇,再捆绑簇并且在另一个簇中显示其内容。
6.00
Numeric
Boolean1 Boolean 2
Tsinghua
String
Input Cluster
6.00
Numeric
Boolean1 Boolean 2
Tsinghua
String
Output Cluster
STOP
stop
Input Cluster
Output Cluster
Unbundle Bundle
Notstop
图3-10 练习3-4的面板和框图
1.打开前面板,创建一个簇壳( Array & Cluster palette),标签改为 Input Cluster,拖曳至适当大小。
2.在这个簇壳中放置一个数字 Control,两个布尔开关,和一个串 Control。
3.仿照以上步骤,创建 Output Cluster 如上。注意将各 Control 改为相应的 indicator。
4.用快速菜单查看两个簇的序是否一致,若有差别,改之。
5.在前面板上设置一个 [STOP]按钮。注意其缺省值为 FALSE,不要改变它的状态。
6.建立如上面所示的流程图。注意在 [STOP]按钮与循环条件端子之间接入了一个 NOT 函数,因为按钮缺省值为 FALSE,经 NOT 函数后变为 TRUE,这就意味着当按钮状态不变时,循环继续执行,相反一旦按钮动作,
则循环终止。在 6i 版本中这个设置可以简化,不必使用 NOT 函数,直接将 [STOP]按钮与循环条件端子相连,然后用鼠标右键点击循环条件端子,选择 stop if true 即可。结果如右图所示。
7.返回前面板并运行 VI。在输入簇中输入不同的值观察输出。
8.关闭并保存程序。 Cluster Exercise.vi
练习 3-4 结束
3.5.3 用名称捆绑与分解簇
有时你并不需要汇集或分解整个簇,而仅仅需要对其一、两个元素操作。这时你可以用名称来捆绑与分解簇。在 Cluster 工具模板中除了 Bundle 及 Unbundle 功能外,还提供有
Bundle By Name 和 Unbundle By Name 功能。它们允许根据元素的名称(而不是其位置)来查询元素。与 Bundle 不同,使用 Bundle By Name 可以访问你需要的元素,但不能创建新簇;
它只能重置一个已经存在的簇的元素,同时你必须给 Bundle By Name 图标中间的输入端子一个输入以申明要替换其元素的簇。 Unbundle 可返回指定名称的簇元素,不必考虑簇的序和大小。例如,如果你想重置上例中 Boolean 2 的值,就可以使用 Bundle By Name 功能而不必担心簇的序和大小。与此类似如果你要访问串的值,可以使用 Unbundle By Name 功能。
0.00
Numeric
TSINGHUA
String
Cluster Control
0.00
Numeric
ABCD
String
Output Element
ABCD
String Control
图3-11 用名称操作簇
在上面的例子中,Cluster Control 中有两个元素,一个是数据类型(名称是 Numeric),
另一个是字符串型(名称是 String),另一个控制是字符串,ABCD”,框图如右所示,运行该程序,即可将簇内的字符串值重置。 (本例中为了使 Bundle By Name 的输入端由 Numeric
变为 String,需使用快速菜单中的 Select Item 项操作。 )
3.5.4 数组和簇的互换
有时你会发现,将数组变为簇(或者相反)很方便。尤其是因为 LabVIEW 包括的关于数组的操作功能多于簇。例如,前面板上有一个多按钮的簇,你希望颠倒这些按钮值的序。
好了,Reverse 1D Array 功能正好可用,但是它仅可用于数组。这没关系,你可以使用功能 Cluster to Array将簇转换为数组,使用 Reverse 1D Array切换开关的值,最后再利用 Array
String Control
Output Element
String
Cluster Control
to Claster 变换回簇。
3.6 Waveform 数据类型
在数据采集和信号分析中经常要遇到波形数据,在 LabVIEW 6i 中增加了 Waveform 数据类型,使得波形的描述更加简洁。 Waveform 数据类型包含了波形的数据 (Y)、起始时刻 (t0)
和步长Δ X,使用 Waveform 模板的 Build Waveform 函数可以建立一个波形。许多用于数据采集和波形分析的 VI 和函数的缺省状态都接受或返回 Waveform 数据类型。当你将一个
Waveform 数据类型连接到 Waveform Graph 或 Chart 时,会自动画出相应的曲线。 Waveform
数据类型是根据原有的数据类型进一步“打包”组合而成,这种打包也不可避免地带来一些负作用,有时还需要对 Waveform 数据类型“解包” 。有关这一数据类型的函数或 VI 在
Functions? Waveform 和 Analyze 之中。
图3-12 使用 Waveform 的波形发生例子
图3-12是一个使用 Waveform 函数产生正弦波的例子。其中仅仅调用了 Sine
Waveform 一个函数,只要将有关参数指定,就可产生正弦波。 Sine Waveform 实际上是一个子 VI,点击其图标,就可看到下层的程序,还是比较复杂的。在 LabVIEW 6I 以前的版本中用户就需要那样去编程。
第四章 图形显示
4.1 概述
图形显示对于虚拟仪器面板设计是一个重要的内容。 LabVIEW 为此提供了丰富的功能。
在前面几章我们已经接触了这个问题,现在较系统地介绍一下。
我们不从图形的实现方法上去讨论问题,那是计算机图形学的课题。但我们需要从用户的可能的需求角度探求一下,如果你需要做虚拟仪器方面的开发,那么可能遇到些什么图形问题。 LabVIEW 在这方面所做的工作是非常值得借鉴的。
在 LabVIEW 的图形显示功能中 Graph 和 Chart 是两个基本的概念。一般说来 Chart 是将数据源(例如采集得到的数据)在某一坐标系中,实时、逐点地显示出来,它可以反映被测物理量的变化趋势,例如显示一个实时变化的波形或曲线,传统的模拟示波器、波形记录仪就是这样。而 Graph 则是对已采集数据进行事后处理的结果。它先将被采集数据存放在一个数组之中,然后根据需要组织成所需的图形显示出来。它的缺点是没有实时显示,但是它的表现形式要丰富得多。例如采集了一个波形后,经处理可以显示出其频谱图。现在,数字示波器也可以具备类似 Graph 的显示功能。
LabVIEW 的 Graph 子模板中有许多可供选用的控件,其中常用的见下表,
Chart Graph
Waveform(波形)
* *
XY *
Intensity(强度图)
* *
Digital(数字图)
*
3D Surface(三维曲面)
3D Parametric(三维参变量)
*
3D Curve(三维曲线)
由表中可以看出,Chart 方式尽管能实时,直接地显示结果,但其表现形式有限,而 Graph
方式表现形式要远为丰富,但这是以牺牲实时为代价的。在 LabVIEW 6 i 版本中还包含有极坐标等其他图形( Plot),本章不讨论。
4.2 Graph 控件
各种图形都提供了相应的控件,以 Graph 为例介绍。图4-1所示为它的控件。所有这些控件都包含在图形快速菜单的 Visible Items 选项下。
曲线图例可用来设置曲线的各种属性,包括线型(实线、虚线、点划线等),线粗细、
颜色以及数据点的形状等。
图形模板可用来对曲线进行操作,包括移动、对感兴趣的区域放大和缩小等。
光标图例可用来设置光标、移动光标,帮助你用光标直接从曲线上读取感兴趣的数据。
刻度图例用来设置坐标刻度的数据格式、类型(普通坐标或对数坐标),坐标轴名称以及刻度栅格的颜色等。
图 4-1 Graph 的图形控件
4.3 Chart 的独有控件
Chart 的数据并没有事先存在一个数组中,它是实时显示的,为了能够看到先前的数据,
Chart 控件内部含有一个显示缓冲器,其中保留了一些历史数据。这个缓冲器按照先进先出的原则管理,其最大容量是 1024 个数据点。
null 滚动条 (Scrollbar)
它直接对应于显示缓冲器,通过它可以前后观察缓冲器内任何位置的数据。
null 数据显示 (Digital Display)
选中它,可以在图形右上角出现一个数字显示器,这样可以在画出曲线的同时显示当前最新的一个数据值。
null 刷新模式 (Update Mode)
Chart 提供了三种画面的刷新模式,分别是
null Strip Chart Mode(条壮图),它与纸带式图表记录仪类似。曲线从左到右连续绘制,
当新的数据点到达右部边界时,先前的数据点逐次左移。
null Scope Chart Mode(示波器模式),它与示波器类似。曲线从左到右连续绘制,当新的数据点到达右部边界时,清屏刷新,从左边开始新的绘制。它的速度较快。
null Sweep Chart Mode(扫描模式),与示波器模式的不同在于当新的数据点到达右部边界时,不清屏,而是在最左边出现一条垂直扫描线,以它为分界线,将原有曲线逐点向右推,同时在左边画出新的数据点。如此循环下去。
曲线图例
刻度图例
(Scale Legend)
图形模板
(Graph Palette)
光标图例
(Cursor Legend)
标签 (Label)
说明
(Caption)
null 堆叠式图区( Stack Plots)
在相同的纵坐标下,由于各种测量信号的差异,将几条曲线显示在同一个图区有困难时,可以组织出一种纵坐标相同,而有各自横坐标的堆叠式图区。
打开\ LabVIEW\ Examples\ Graphs\ chart.lib 目录的 Charts.vi,那里提供了有关
Chart 的各种形态的例子,以及堆叠式图区的例子
练习 4-1 Chart和 Graph 的比较
目的:创建一个 VI,用 Chart 和 Graph 分别显示 40 个随机数产生的曲线,比较程序的差别。
前面板及流程图如下
图4-2 Chart和 Graph 的比较
显示的运行结果是一样的。但实现方法和过程不同。在流程图中可以看出,Chart 产生在循环内,每得到一个数据点,就立刻显示一个。而 Graph 在循环之外,40 个数都产生之后,跳出循环,然后一次显示出整个数据曲线。从运行过程可以清楚地看到这一点。
值得注意的还有 For 循环执行 40 次,产生的 40 个数据存储在一个数组中,这个数组创建于 For 循环的边界上(使用自动索引功能) 。在 For 循环结束之后,该数组就将被传送到外面的 Graph。仔细看流程图,穿过循环边界的连线在内、外两侧粗细不同,内侧表示浮点数,外侧表示数组。
练习 4-1 结束
4.4 XY 图形控件( XY Graph)
波形图( Waveform Graph)有一个特征,其 X 是测量点序号、时间间隔等,Y 是测量数据值。但是它并不适合描述一般的 Y 值随 X 值变化曲线。适合于这种情况的控件是 XY
Graph。我们通过一个构成利萨育图形的例子来看一下它的使用。我们知道如果控制 XY 方向的两个数组分别按正弦规律变化(假设其幅值、频率都相同),如果它们的相位相同,则利萨育图形是一条 45 度的斜线,当它们之间相位差 90 度时为圆,其他相位差是椭圆。
40
Waveform Chart
100
Waveform Graph
练习4-2 利用 XY Graph 构成利萨育图形。
图4-3 利用 XY Graph 构成利萨育图形
面板和框图如图4-3所示。 面板上除了一个 XY Graph 外,还有一个相位差输入控件。
在框图中使用了两个 Sine Waveform.vi,第一个所有输入参数(包括频率、幅值、相位等)
都使用缺省值,所以其初始相位为0。第二个将其初始相位作为一个控件引到面板上。它们的输出是包括 t0,dt 和 Y 值的簇,但是对于 XY Graph 只需要其中的 Y 数组,因此使用波形函数中的 Get Waveform Components 函数分别提取出各自的 Y 数组,然后再将他们捆绑在一起,连接到 XY Graph 就可以了。当相位置为 45 度时,运行程序,得到如图所示的椭圆。
注意,claster/Bundle
练习 4-2 结束
4.5 强度图形控件( Intensity Graph)
强度图形控件提供了一种在二维平面上表现三维数据的方法。 例如可以用屏幕色彩的亮度来反映来反映一个二维数组元素值的大小。 图4-3就是这样的一个例子。 注意图中的 x、
y 轴刻度对应的是数组行、列的序号。
图4-4 用强度图形表现一个二维数组及其元素值的大小
4.6 数字波形图控件( Digital Waveform Graph)
该控件的例子见图4-5。面板上有一个输入控制,共输入了7个十进制数,还有一个二进制显示对象,显示了这些十进制数对应的二进制数,最右边是一个 Digital Waveform
Graph。注意这个图中数据应当从纵方向读出,在横坐标上的刻度是数据的序号(0到6),
其中最后一个数的序号是6,纵坐标从下向上读是 11111111,第一个数的序号是0,其值从上向下读是 00000001,而第二个数(序号1)是 00000010。
图4-5 数字波形图控件的例图
该程序的框图中值得注意的问题有以下几点,
null 十进制数可以直接送给 Digital Waveform Graph,不必事先转化为二进制数。
null 在送给 Digital Waveform Graph 之前,需要经过一个捆绑( bundle 函数) 。
null 捆绑的顺序是 x0,deltx,输入数据,最后是 Number of Ports。这里的 Number of Ports 将反映二进制的位数或字长,为1时是8位,为2时变为1
6位,余类推。
4.7 3D 图形显示控件( 3D Graph)
二进制显示
Digital Waveform Graph
输入数据
1
Number of Ports
1.0
DeltaX
0.00
X0
第五章 字符串和文件I/O
5.1 字符串
字符串是 ASCII 字符的集合。如同其他语言一样,LabVIEW 也提供了各种处理字符串的功能,如果想获得字符串的例子,可查看 Examples\ General\ strings.llb。下面扼要介绍一些内容。
null 创建字符串控制对象和显示对象
可以在 Controls?String & Table 中看到右边所显示字符串控制对象和显示对象。还可以使用操作工具或者标签工具输入或者改变字符串控制对象中的文本。 用移位工具拖曳字符串控制对象和显示对象的边角可以增大它们的面积。
在这里输入文本字符串 control
练习 5-1 组合字符串
目的:使用一些字符串功能函数将一个数值转换成字符串,并把该字符串和其他一些字符串连接起来组成一个新的输出字符串。
前面板
打开一个新的前面板,按照下图向其中添加对象。
SET
Header
VOLTS
Trailer
5.50
Number
SET 5.5000 VOLTS
输出字符串
16
输出串长度
其中的两个字符串控制对象和数值控制对象可以合并成一个输出字符串并显示在字符串显示器中。数值显示器显示出字符串的长度。
本练习中输出字符串是一个 GPIB( IEEE 488)命令字符串,它可用来与和串口仪器
( RS-232 或者 RS-422)进行通信。
流程图
%s %.4f %s
输出串长度输出字符串
Number
Trailer
Header
null Format Into String 函数( Functions?String)——在本练习中,它用于对数值和字符串进行格式化,使它们成为一个输出字符串。用变形工具可以添加三个加和输入。
null String Length 函数( Functions?String)——在本练习中,它用于返回一个字符串的字节数
null 执行该 VI。注意,Format Into String 功能函数将两个字符串控制对象和数值控制对象组合成一个输出字符串。
null 把该 VI 保存为 Build String.vi,在下一个练习中还将用到这个 VI。
null 字符串格式的设定:选中 Format Into String 函数,单击右键,在快速菜单中选择 Edit
Format String,可分别对个输入的各部分格式做设定。
练习 5-1 结束。
练习 5-2 字符串子集和数值的提取
目的:创建一个字符串的子集,其中含有某个数值的字符串显示,再将它转换成数值。
打开 Examples\General\strings.llb 中的 Parse String.vi。用默认输入值执行该 VI。注意,
DC 的字符串子集被用于输入字符串。还要注意,字符串的数值部分被提取出来,并转换为数值。您可以尝试使用不同的控制数值(记住数组式的字符串是从 0 开始进行编号),或者您可以返回到流程图,查看怎样从输入字符串中提取出其中的元素。
String Subset 函数( Functions?String)——在本练习中,它用于返回偏移地址开始的子字符串以及字节数。第一个偏移地址是 0。
很多情况下,必须把字符串转换成数值,例如需要将从仪器中得到的数据字符串转换成数值。
Scan From String 函数( Functions?String)——在这个例子中,它用于扫描字符串,并将有效的数值( 0 到 9,正负,e,E 和分号)转换成数值。如果连接了一个格式字符串,它将根据字符串指定的格式进行转换,否则将进行默认格式的转换。
该函数从偏移地址的 string 处开始扫描。第一个字符的偏移地址是 0。这个函数在已知头长度(本例中是 VOLTS DC)时或者字符串只含有有效字符时很有用。
选择 File?Close,关闭该 VI。注意不要保存它。
练习 5-2 结束。
5.2 文件的输入 /输出( I/O)
文件 I/O 功能函数是一组功能强大,伸缩性强的文件处理工具。 它们不仅可以读写数据,
还可以移动、重命名文件与目录。创建电子表格格式的、由可读的 ASCII 文本组成的文件,
以及为了提高读写速度和压缩率采用二进制的格式写入数据。
可以采用下面三种文件格式存储或者获得数据,
null ASCII 字节流——如果希望让其他的软件(譬如字处理程序或者电子表格程序)也可以访问数据,就需要将数据存储为 ASCII 格式。为此,您需要把所有数据都转换为 ASCII
字符串。
null 数据记录文件——这种文件采用的是只有 G 语言可以访问的二进制格式。 数据记录文件类似于数据库文件,因为它可以把不同的数据类型存储到同一个文件记录中。
null 二进制字节流——这种文件的格式是最紧凑、最快速地存储文件的格式。您必须把数据转换成二进制字符串的格式,还必须清楚地知道在对文件读写数据时采用的是哪种数据格式。
因为 ASCII 字节流格式是最常用的数据文件格式,所以本节着重介绍这种格式。如果您想获得关于文件 I/O 的例子,请参考 Examples\ File。
5.2.1 文件 I/O 功能函数
大多数的文件 I/O 操作都包括三个基本的步骤:打开一个已有的文件或者新建一个文件;对文件进行读写;关闭文件。 LabVIEW 在 Functions? File I/O 中提供了很多有用的工具 VI。本节主要介绍 9 个高级工具 VI,这些工具 VI 可以把错误检查和错误处理等功能与文件 I/O 功能函数结合起来。
以下5个功能从左到右对应于上面5个图标。
null Write To Spreadsheet File VI——用于将由单精度数值组成的一维或者二维数组转换成文本字符串,再将它写入一个新建文件或者已有文件。该 VI 先打开或者新建文件,之后再关闭文件。它可以用于创建能够被大多数电子表格软件读取的文本文件。
null Read From Spreadsheet File VI——用于从某个文件的特定位置开始读取指定个数的行或者列内容,再将数据转换成二维、单精度数组。该 VI 先打开文件,之后再关闭文件。它可以用于读取用文本格式存储的电子表格文件。
null Write Characters To File VI——用于将一个字符串写入一个新建文件或者已有文件。该 VI 打开这个文件、写入数据,再关闭文件。
null Read Characters From File VI——用于从某个文件的特定位置开始读取指定个数的字符。该 VI 先打开文件,之后再关闭文件。
null Read Lines From File VI——用于从某个文件的特定位置开始读取指定个数的行内容。该 VI 先打开文件,之后再关闭文件。
如果想查看其他的文件 I/O 功能函数,请选择 Function?File I/O? Binary File VIs 或者 Function?File I/O?Advanced File Functions。
5.2.2 将数据写入电子表格文件
将数据存储到文件的最常见应用之一是设置文本文件的格式以便在电子表格文件中打开它。大多数电子表格文件用 Tab 键分割各列,而用 EOL(段尾)分隔各行,如下图所示。
用一个电子表格程序(如 Excel)打开该文件可以看到下面这个表格。
练习 5-3 将数据写入电子表格文件
目的:修改一个已有的 VI 以使用文件 I/O 功能函数,以便可以将数据以 ASCII 格式保存到一个新的文件。然后就可以用一个电子表格程序打开该文件。
前面板
打开前面练习中创建的 Graph Waveform Arrays.vi。当调用这个 VI 时,该 VI 将产生两个数据数组,并将它们绘制在一个图区中。您需要对该 VI 进行修改,从而把两个数组写入一个文件,格式是每列含有一个数组。
-0.09
0
Array
1.5
-0.5
0.0
0.5
1.0
1000 10 20 30 40 50 60 70 80 90
Plot 0
Plot 1
Waveform Graph
don't transpose
transpose? (no:F)
流程图
打开 Graph Waveform Arrays.vi 的流程图,按照下图在流程图的右下角添加功能函数。
null Write To Spreadsheet File VI ( Functions?File I/O)用于将二维数组转换成电子表格字符串,再将它写入一个文件。如果没有指定路径名称,
将会弹出一个文件对话框,提示输入文件名。该 VI 将把一维或者二维数组写入文件。这个例子中,因为用的是二维数组,所以无需连接一维输入端子。
transpose? (no:F)
Build Array
0.5
100
50
Waveform Graph
Array
null Boolean 常数 ( Functions?Boolean)用于控制是否在写入数据之前转换成二维数组。
在这个例子中需要对数据进行转换。因为电子表格文件的每列都含有一个数据数组,所以必须先转换成二维数组。
null 返回前面板,执行该 VI。数据数组产生以后,会出现一个文件对话框提示输入新建文件的文件名。输入文件名,并单击 OK。
null 可以尝试选择转换与不转换两种情况运行程序,查看结果差别。
null 保存该 VI 为 Waveform Arrays to File.vi,并关闭该 VI。
现在可以用电子表格软件或者文本编辑器打开或者编辑刚才创建的文件。可以看到两列表格,每列含有 100 个元素。
在这个例子中,直到所有数组都被采集以后,数据才可以被转换或者写入文件。如果需要更大的数据缓存和希望在数据产生后把它们写入到硬盘,就需要使用另外一个文件 I/O VI。
练习 5-3 结束。
练习 5-4 向文件添加数据
目的:创建一个 VI,可以把温度数据以 ASCII 格式添加到某个文件中。该 VI 使用 For 循环产生温度数据,并将它们存储到一个文件中。在每个循环期间,您都要把数据转换成字符串,添加一个逗号作为分隔符,并将字符串添加到文件中。
前面板
打开一个新的前面板,并按照下图放置对象。
20
数据点个数
90.0
70.0
75.0
80.0
85.0
5939
84.96
温度 Chart
new file
append to file?
前面板中包括一个数字式显示器和一个波形图。,数据点个数”控制对象指定了需要采集和写入文件的温度数据的数量。波形图表则用于显示温度曲线。将波形图表的 Y 轴范围设置为 70.0 到 90.0,X 轴范围设置为 0 到 20。
流程图
温度 Chart
append to file?
%f,
数据点个数
null 打开流程图,添加 For 循环并增大它的面积。该 VI 将产生由“数据点个数”控制对象指定的个数的温度数据。
null 在循环中加一个移位寄存器,方法是用鼠标右键单击循环边界,在快捷菜单中选择移位寄存器。这个移位寄存器中将含有文件的路径名。
null 完成对象的连线。
null Empty Path 常数( Functions?File I\ O?File Constants)——用于初始化移位寄存器,以保证需要对文件写入数据时路径都是空的。会出现一个文件对话框提示输入文件名。
null Digital Thermometer VI( Functions?Select a VI… )——返回一个模拟温度测量值(仿真) 。
null Format Into String 函数( Functions?String)——将温度数据转换成字符串,并且在数据后面增加一个逗号。
null Write Characters To File VI( (Functions?File I/O)——用于向文件写入字符串。
null Boolean 常数( Functions?Boolean)用于将 Write Characters To File VI 的 append to
file?输入为 TRUE,这样在循环执行时新的温度数据就会加入到选中的文件中。用操作工具单击这个常数可以将它设置为 TRUE。
null 返回前面板,把“数据点个数”设置为 20,执行该 VI。这时会出现一个文件对话框,
提示输入文件名。输入文件名以后,VI 就会在每个温度数据产生时,将它写入到该文件中。
null 把该 VI 保存为 LabVIEW\ Activity 目录下的 Write Temperature to File.vi。
null 使用任意一个字处理软件,例如 Write for Windows,Teach Text for Macintosh,或者 UNIX 平台下的某个文本编辑器,打开该数据文件查看其内容。您可以看到文件的内容是 20 个用逗号分隔开的数值(准确到小数点后三位) 。
练习 5-4 结束。
练习 5-5 从文件读取数据
目的:创建一个 VI,可以从上一个练习中创建的例子中读取数据,并把这些数据显示在一个波形图形中。必须按照数据保存的格式来读取它,因为原来是用字符串数据类型,把数据保存为 ASCII 格式,那么就必须用一个文件 I/O 函数把数据作为字符串读出。
前面板
打开一个新的前面板,并按照下图放置对象。
87.402344,
86.914062,
86.425781,
85.937500,
85.449219,
85.449219,
84.960937,
84.472656,
83.984375,
83.984375,
83.984375,
83 984375
从文件读字符串
100.0
50.0
60.0
70.0
80.0
90.0
100 1 2 3 4 5 6 7 8 9
温度 Graph
前面板中包括一个字符串显示对象和一个波形图。“从文件读字符串“显示对象将从上个练习创建的文件中读出用逗号分隔开的温度数据。波形图则用于显示温度曲线。
流程图
Read Characters From File.vi
温度 Graph
从文件读字符串
null Read Characters From File VI( Functions?File I/O)——用于从文件中读取数据,以及输入字符串中的信息。如果没有指定路径名称,将出现一个文件对话框提示您输入文件名。在这个例子中,无需判断需要读取的字符的个数,因为文件的字符数比默认的 512 要少。要从文件中读取数据,必须知道数据的存储方式。如果知道了文件的长度,就可以使用 Read Characters From File VI 读取指定个数的字符。
null Extract Numbers VI (Examples\ General\ strings.llb)——用于提取由逗号、分行符号、非数值字符等分隔开的数据组成的 ASCII 字符串,并将它们转换成数值数组。
null 返回前面板,执行该 VI。将出现一个文件对话框,在其中选择刚才保存的数据文件,
您可以看到图形中显示的数据与 Write Temperature to File VI 例子中显示的一样。
null 保存该 VI 为 Temperature from File.vi,并关闭它。
练习 5-5 结束。
5.3 数据记录文件( datalog file)
上面提供的例子说明了处理 ASCII 字符格式存储的数据的文件的简单方法。 在需要创建供其他软件(如电子表格软件)访问的文件时这种方法很有用。另外一种是称为数据记录文件( datalog file)的数据格式。它与数据库文件有类似之处,文件是由记录组成的,一个文件的所有记录有相同的结构和长度。访问该文件是可以以记录为单位,并且可直接访问文件中的任意一个记录。记录本身的数据结构可由用户自己定义,一个记录内可容纳不同的数据类型,它就像一个簇一样。
如果要用 VI 获得数据,您可能不想把数据写入到 ASCII 文件中,因为把数据和字符串之间相互转换非常花费时间。例如,把一个二维的字符转换成一个具有电子表格格式的字符串(具有标题和时间标记)也是一个非常复杂的操作。如果不需要把文件存储成可供别的软件访问的格式,您可以把数据输出到一个数据记录文件。使用这种格式时,把数据写入到文件的操作变得非常简单,这也使得读写操作的速度更快。它还可以简化数据采集的工作,因为您可以把初始的数据块作为一个日志或者记录读取,而无需了解其中含有多少数据。 G 语言会记录数据的数量,用于对每个数据记录文件的记录。
Write Datalog File 示例(位于 Examples\ File\ datalog.llb)创建了一个新的数据记录文件,并把指定数目的数据写入该文件。每个记录都是一个由一个字符串和一个单精度数据数组构成的簇。
要读取一个数据记录文件,您采用的格式必须与对该文件写入数据时所用格式相同。 Read
Datalog File示例将从 Write Datalog File示例创建的数据记录文件中一次读取一个记录。
读出的每个记录都是一个由一个字符串和一个单精度数据数组构成的簇。
第六章 数据采集
6.1 概述
在计算机广泛应用的今天,数据采集的重要性是十分显著的。它是计算机与外部物理世界连接的桥梁。各种类型信号采集的难易程度差别很大。实际采集时,噪声也可能带来一些麻烦。数据采集时,有一些基本原理要注意,还有更多的实际的问题要解决。
6.1.1 采样频率、抗混叠滤波器和样本数。
假设现在对一个模拟信号 x(t) 每隔Δ t 时间采样一次。时间间隔Δ t 被称为采样间隔或者采样周期。它的倒数 1/Δ t 被称为采样频率,单位是采样数 /每秒。 t=0,Δ t,2Δ t,3
Δ t ……等等,x(t)的数值就被称为采样值。所有 x(0),x(Δ t),x(2Δ t )都是采样值。这样信号 x(t)可以用一组分散的采样值来表示,
下图显示了一个模拟信号和它采样后的采样值。采样间隔是Δ t,注意,采样点在时域上是分散的。
图 6-1 模拟信号和采样显示
如果对信号 x(t)采集 N 个采样点,那么 x(t)就可以用下面这个数列表示,
这个数列被称为信号 x(t)的数字化显示或者采样显示。注意这个数列中仅仅用下标变量编制索引,而不含有任何关于采样率(或Δ t)的信息。所以如果只知道该信号的采样值,并不能知道它的采样率,缺少了时间尺度,也不可能知道信号 x(t)的频率。
根据采样定理,最低采样频率必须是信号频率的两倍。 反过来说,如果给定了采样频率,
那么能够正确显示信号而不发生畸变的最大频率叫做恩奎斯特频率,它是采样频率的一半。
如果信号中包含频率高于奈奎斯特频率的成分,信号将在直流和恩奎斯特频率之间畸变。图
6-2显示了一个信号分别用合适的采样率和过低的采样率进行采样的结果。
采样率过低的结果是还原的信号的频率看上去与原始信号不同。 这种信号畸变叫做混叠
( alias) 。出现的混频偏差( alias frequency)是输入信号的频率和最靠近的采样率整数倍的差的绝对值。
图 6-2 不同采样率的采样结果
图6-3给出了一个例子。假设采样频率 fs 是 100HZ,,信号中含有 25,70,160、
和 510 Hz 的成分。
图6-3 说明混叠的例子
采样的结果将会是低于奈奎斯特频率( fs/2=50 Hz)的信号可以被正确采样。而频率高于
50HZ 的信号成分采样时会发生畸变。分别产生了 30,40 和 10 Hz 的畸变频率 F2,F3 和 F4。
计算混频偏差的公式是,
混频偏差= ABS(采样频率的最近整数倍-输入频率)
其中 ABS 表示“绝对值”,例如,
混频偏差 F2 = |100 – 70| = 30 Hz
混频偏差 F3 = |(2)100 – 160| = 40 Hz
混频偏差 F4 = |(5)100 – 510| = 10 Hz
为了避免这种情况的发生,通常在信号被采集( A/D)
之前,经过一个低通滤波器,将信号中高于奈奎斯特频率的信号成分滤去。在图6-3的例子中,这个滤波器的截止频率自然是
a 足够的采样率下的采样结果
b 过低采样率下的采样结果
25HZ。这个滤波器称为 抗混叠滤波器
采样频率应当怎样设置呢?也许你可能会首先考虑用采集卡支持的最大频率。但是,较长时间使用很高的采样率可能会导致没有足够的内存或者硬盘存储数据太慢。 理论上设置采样频率为被采集信号最高频率成分的2倍就够了,实际上工程中选用
5~10倍,有时为了较好地还原波形,甚至更高一些。
通常,信号采集后都要去做适当的信号处理,例如 FFT 等。
这里对样本数又有一个要求,一般不能只提供一个信号周期的数据样本,希望有5~10个周期,甚至更多的样本。并且希望所提供的样本总数是整周期个数的。这里又发生一个困难,有时我们并不知道,或不确切知道被采信号的频率,因此不但采样率不一定是信号频率的整倍数,也不能保证提供整周期数的样本。我们所有的仅仅是一个时间序列的离散的函数 x(n)和采样频率。
这是我们测量与分析的唯一依据。
6.1.2 数据采集系统的构成
图6-4 数据采集系统结构
上图表示了数据采集的结构。在数据采集之前,程序将对采集板卡初始化,板卡上和内存中的 Buffer 是数据采集存储的中间环节。需要注意的两个问题是:是否使用 Buffer?是否使用外触发启动、停止或同步一个操作。
缓冲( Buffers)
这里的缓冲指的是 PC 内存的一个区域(不是数据采集卡上的 FIFO 缓冲),它用来临时存放数据。例如,你需要采集每秒采集几千个数据,在一秒内显示或图形化所有数据是困难的。但是将采集卡的数据先送到 Buffer,你就可以先将它们快速存储起来,稍后再重新找回它们显示或分析。 需要注意的是 Buffer 与采集操作的速度及容量有关。 如果你的卡有 DMA
性能,模拟输入操作就有一个通向计算机内存的高速硬件通道,这就意味着所采集的数据可以直接送到计算机的内存。
不使用 Buffer 意味着对所采集的每一个数据你都必须及时处理(图形化、分析等),因为这里没有一个场合可以保持你着手处理的数据之前的若干数据点。
下列情况需要使用 Buffer I/O,
null 需要采集或产生许多样本,其速率超过了实际显示、存储到硬件,或实时分析的速度。
null 需要连续采集或产生 AC 数据( >10 样本/秒),并且要同时分析或显示某些数据。
null 采样周期必须准确、均匀地通过数据样本。
下列情况可以不使用 Buffer I/O,
null 数据组短小,例如每秒只从两个通道之一采集一个数据点。
null 需要缩减存储器的开支。
触发( Triggering)
触发涉及初始化,终止或同步采集事件的任何方法。 触发器通常是一个数字或模拟信号,
其状态可确定动作的发生。软件触发最容易,你可以直接用软件,例如使用布尔面板控制去启动 /停止数据采集。硬件触发让板卡上的电路管理触发器,控制了采集事件的时间分配,
有很高的精确度。硬件触发可进一步分为外部触发和内部触发。当某一模入通道发生一个指定的电压电平时,让卡输出一个数字脉冲,这是内部触发。采集卡等待一个外部仪器发出的数字脉冲到来后初始化采集卡,这是外部触发。许多仪器提供数字输出(常称为,trigger
out” )用于触发特定的装置或仪器,在这里,就是数据采集卡。
下列情况使用软件触发,
null 用户需要对所有采集操作有明确的控制,并且
null 事件定时不需要非常准确。
下列情况使用硬件触发,
null 采集事件定时需要非常准确。
null 用户需要削减软件开支。
null 采集事件需要与外部装置同步。
后面可以看到怎样使用采集的 VI 程序设置有 Buffer 及无 Buffer 的 I/O 操作,以及设置触发的类型。
6.1.3 模入信号类型
数据采集前,必须对所采集的信号的特性有所了解,因为不同信号的测量方式和对采集系统的要求是不同的,只有了解被测信号,才能选择合适的测量方式和采集系统配置。
任意一个信号是随时间而改变的物理量。一般情况下,信号所运载信息是很广泛的,
比如:状态( state),速率 (rate)、电平 (level)、形状 (shape)、频率成分 (frequency
content)。根据信号运载信息方式的不同,可以将信号分为模拟或数字信号。数字 (二进制 )
信号分为开关信号和脉冲信号。模拟信号可分为直流、时域、频域信号,如图 6-5 所示。
图 6-5 信号分类
数字信号
第一类数字信号是开 -关信号。一个开 -关信号运载的信息与信号的瞬间状态有关。 TTL
信号就是一个开 -关信号,一个 TTL 信号如果在 2.0 到 5.0V 之间,就定义它为逻辑高电平,
如果在 0 到 0.8V 之间,就定义为逻辑低电平。
第二类数字信号是脉冲信号。这种信号包括一系列的状态转换,信息就包含在状态转化发生的数目、转换速率、一个转换间隔或多个转换间隔的时间里。安装在马达轴上的光学编码器的输出就是脉冲信号。有些装置需要数字输入,比如一个步进式马达就需要一系列的数字脉冲作为输入来控制位置和速度。
模拟直流信号
模拟直流信号是静止的或变化非常缓慢的模拟信号。 直流信号最重要的信息是它在给定区间内运载的信息的幅度。常见的直流信号有温度、流速、压力、应变等。采集系统在采集模拟直流信号时,需要有足够的精度以正确测量信号电平,由于直流信号变化缓慢,用软件计时就够了,不需要使用硬件计时。
模拟时域信号
模拟时域信号与其他信号不同在于,它在运载信息时不仅有信号的电平,还有电平随时间的变化。在测量一个时域信号时,也可以说是一个波形,需要关注一些有关波形形状的特性,比如斜度、峰值等。为了测量一个时域信号,必须有一个精确的时间序列,序列的时间间隔也应该合适,以保证信号的有用部分被采集到。要以一定的速率进行测量,这个测量速率要能跟上波形的变化。用于测量时域信号的采集系统包括一个 A/ D、一个采样时钟和一个触发器。 A/ D 的分辨率要足够高,保证采集数据的精度,带宽要足够高,用于高速率采样;精确的采样时钟,用于以精确的时间间隔采样;触发器使测量在恰当的时间开始。存在许多不同的时域信号,比如心脏跳动信号、视频信号等,测量它们通常是因为对波形的某些方面特性感兴趣。
模拟频域信号
模拟频域信号与时域信号类似,然而,从频域信号中提取的信息是基于信号的频域内容,
而不是波形的形状,也不是随时间变化的特性。用于测量一个频域信号的系统必须有一个 A
/ D、一个简单时钟和一个用于精确捕捉波形的触发器。系统必须有必要的分析功能,用于从信号中提取频域信息。为了实现这样的数字信号处理,可以使用应用软件或特殊的 DSP
硬件来迅速而有效地分析信号。模拟频域信号也很多,比如声音信号、地球物理信号、传输信号等。
上述信号分类不是互相排斥的。一个特定的信号可能运载有不只一种信息,可以用几种方式来定义信号并测量它,用不同类型的系统来测量同一个信号,从信号中取出需要的各种信息。
6.1.4 模入信号的连接方式
一个电压信号可以分为接地和浮动两种类型。测量系统可以分为差分( Differential),
参考地单端( RSE),无参考地单端( NRSE)三种类型。
1.接地信号和浮动信号
接地信号
接地信号,就是将信号的一端与系统地连接起来,如大地或建筑物的地。因为信号用的是系统地,所以与数据采集卡是共地的。接地最常见的例子是通过墙上的接地引出线,如信号发生器和电源。
浮动信号
一个不与任何地(如大地或建筑物的地)连接的电压信号称为浮动信号,浮动信号的每个端口都与系统地独立。 一些常见的浮动信号的例子有电池,热电偶,变压器和隔离放大器。
2.测量系统分类
差分测量系统
差分测量系统中,信号输入端分别与一个模入通道相连接。具有放大器的数据采集卡可配置成差分测量系统。图 6-6 描述了一个 8 通道的差分测量系统,用一个放大器通过模拟多路转换器进行通道间的转换。标有 AIGND(模拟输入地)的管脚就是测量系统的地。
图 6-6 差分测量系统
一个理想的差分测量系统仅能测出( +)和( -)输入端口之间的电位差,完全不会测量到共模电压。然而,实际应用的板卡却限制了差分测量系统抵抗共模电压的能力,数据采集卡的共模电压的范围限制了相对与测量系统地的输入电压的波动范围。 共模电压的范围关系到一个数据采集卡的性能,可以用不同的方式来消除共模电压的影响。如果系统共模电压超过允许范围,需要限制信号地与数据采集卡的地之间的浮地电压,以避免测量数据错误。
参考地单端测量系统 (RSE)
一个 RSE 测量系统,也叫做接地测量系统,被测信号一端接模拟输入通道,另一端接系统地 AIGND。图 6-7 描绘了一个 16 通道的 RSE 测量系统。
无参考地单端测量系统 (NRSE)
在 NRSE 测量系统中,信号的一端接模拟输入通道,另一端接一个公用参考端,但这个参考端电压相对于测量系统的地来说是不断变化的。图 6-8 说明了一个 NRSE 测量系统,其中 AISENSE 是测量的公共参考端,AIGND 是系统的地 。
图 6-7 参考地单端测量系统
图 6-8 无参考地单端测量系统
3.选择合适的测量系统
两种信号源和三种测量系统一共可以组成六种连接方式,
接地信号 浮动信号
DEF
* *
RSE
**
NRSE
* *
其中,不带 *号的方式不推荐使用。一般说来,浮动信号和差动连接方式可能较好。但实际测量时还要看情况而定。
测量接地信号
测量接地信号最好采用差分或 NRSE 测量系统。如果采用 RSE 测量系统时,将会给测量结果带来较大的误差。图 6-9 展示了用一个 RSE 测量系统去测量一个接地信号源的弊端。
在本例中,测量电压 Vm 是测量信号电压 Vs 和电位差 DVg 之和,其中 DVg 是信号地和测量地之间的电位差,这个电位差来自于接地回路电阻,可能会造成数据错误。一个接地回路通常会在测量数据中引入频率为电源频率的交流和偏置直流干扰。 一种避免接地回路形成的办法就是在测量信号前使用隔离方法,测量隔离之后的信号。
图 6-9 RSE 测量系统引入接地回路电压
如果信号电压很高并且信号源和数据采集卡之间的连接阻抗很小,也可以采用 RSE 系统,因为此时接地回路电压相对于信号电压来说很小,信号源电压的测量值受接地回路的影响可以忽略。
测量浮动信号
可以用差分,RSE,NRSE 方式测量浮动信号。在差分测量系统中,应该保证相对于测量地的信号的共模电压在测量系统设备允许的范围之内。如果采用差分或 NRSE 测量系统,
放大器输入偏置电流会导致浮动信号电压偏离数据采集卡的有效范围。为了稳住信号电压,
需要在每个测量端与测量地之间连接偏置电阻,如图 6-10 所示。这样就为放大器输入到放大器的地提供了一个直流通路。这些偏置电阻的阻值应该足够大,这样使得信号源可以相对于测量地浮动。对低阻抗信号源来说,10kΩ到 100kΩ的电阻比较合适。
图 6-10 增加偏置电阻
如果输入信号是直流,就只需要用一个电阻将( -)端与测量
系统的地连接起来。然而如果信号源的阻抗相对较高,从免除干扰的角度而言,这种连接方式会导致系统不平衡。在信号源的阻抗足够高的时候,应该选取两个等值电阻,一个连接信号高电平( +)到地,一个连接信号低电平( -)到地。如果输入信号是交流,就需要两个偏置电阻,以达到放大器的直流偏置通路的要求。
总的来说,不论测接地还是浮动信号,差分测量系统是很好的选择,因为它不但避免了接地回路干扰,还避免了环境干扰。相反的,RSE 系统却允许两种干扰的存在,在所有输入信号都满足以下指标时,可以采用 RSE 测量方式:输入信号是高电平(一般要超过 1V) ;
连线比较短 (一般小于 5 米) 并且环境干扰很小或屏蔽良好; 所有输入信号都与信号源共地。
当有一项不满足要求时,就要考虑使用差分测量方式。
另外需要明确信号源的阻抗。电池,RTD、应变片、热电偶等信号源的阻抗很小,可以将这些信号源直接连接到数据采集卡上或信号调理硬件上。 直接将高阻抗的信号源接到插入式板卡上会导致出错。为了更好的测量,输入信号源的阻抗与插入式数据采集卡的阻抗相匹配。
6.1.5 信号调理
从传感器得到的信号大多要经过调理才能进入数据采集设备,信号调理功能包括放大、
隔离、滤波、激励、线性化等。由于不同传感器有不同的特性,因此,除了这些通用功能,
还要根据具体传感器的特性和要求来设计特殊的信号调理功能。 下面仅介绍信号调理的通用功能。
1.放大
微弱信号都要进行放大以提高分辨率和降低噪声,使调理后信号的电压范围和 A/D 的电压范围相匹配。 信号调理模块应尽可能靠近信号源或传感器,使得信号在受到传输信号的环境噪声影响之前已被放大,使信噪比得到改善。
2.隔离
隔离是指使用变压器、光或电容耦合等方法在被测系统和测试系统之间传递信号,避免直接的电连接。使用隔离的原因由两个:一是从安全的角度考虑;另一个原因是隔离可使从数据采集卡读出来的数据不受地电位和输入模式的影响。 如果数据采集卡的地与信号地之间有电位差,而又不进行隔离,那么就有可能形成接地回路,引起误差。
3.滤波
滤波的目的是从所测量的信号中除去不需要的成分。大多数信号调理模块有低通滤波器,用来滤除噪声。通常还需要抗混叠滤波器,滤除信号中感兴趣的最高频率以上的所有频率的信号。某些高性能的数据采集卡自身带有抗混叠滤波器。
4.激励
信号调理也能够为某些传感器提供所需的激励信号,比如应变传感器、热敏电阻等需要外界电源或电流激励信号。很多信号调理模块都提供电流源和电压源以便给传感器提供激励。
5.线性化
许多传感器对被测量的响应是非线性的,因而需要对其输出信号进行线性化,以补偿传感器带来的误差。但目前的趋势是,数据采集系统可以利用软件来解决这一问题。
6.数字信号调理
即使传感器直接输出数字信号,有时也有进行调理的必要。其作用是将传感器输出的数字信号进行必要的整形或电平调整。大多数数字信号调理模块还提供其他一些电路模块,使得用户可以通过数据采集卡的数字 I/O 直接控制电磁阀、电灯、电动机等外部设备。
6.1.6 数据采集 (DAQ)卡
1.数据采集卡的功能
一个典型的数据采集卡的功能有模拟输入、模拟输出、数字 I/O、计数器 /计时器等,这些功能分别由相应的电路来实现。
模拟输入是采集最基本的功能。它一般由多路开关( MUX),放大器、采样保持电路以及 A/D 来实现,通过这些部分,一个模拟信号就可以转化为数字信号。 A/D 的性能和参数直接影响着模拟输入的质量,要根据实际需要的精度来选择合适的 A/D。
模拟输出通常是为采集系统提供激励。输出信号受数模转换器( D/A)的建立时间、转换率,分辨率等因素影响。 建立时间和转换率决定了输出信号幅值改变的快慢。 建立时间短、
转换率高的 D/A 可以提供一个较高频率的信号。 如果用 D/A 的输出信号去驱动一个加热器,
就不需要使用速度很快的 D/A,因为加热器本身就不能很快地跟踪电压变化。应该根据实际需要选择 D/A 的参数指标。
数字 I/O 通常用来控制过程、产生测试信号、与外设通信等。它的重要参数包括:数字口路数( line),接收 (发送 )率、驱动能力等。如果输出去驱动电机、灯、开关型加热器等用电器,就不必用较高的数据转换率。路数要能同控制对象配合,而且需要的电流要小于采集卡所能提供的驱动电流。但加上合适的数字信号调理设备,仍可以用采集卡输出的低电流的 TTL 电平信号去监控高电压、大电流的工业设备。数字 I/O 常见的应用是在计算机和外设如打印机,数据记录仪等之间传送数据。 另外一些数字口为了同步通信的需要还有,握手”
线。路数、数据转换速率,“握手”能力都是应理解的重要参数,应依据具体的应用场合而选择有合适参数的数字 I/O。
许多场合都要用到计数器,如定时、产生方波等。计数器包括三个重要信号:门限信号、
计数信号、输出。门限信号实际上是触发信号——使计数器工作或不工作;计数信号也即信号源,它提供了计数器操作的时间基准;输出是在输出线上产生脉冲或方波。计数器最重要的参数是分辨率和时钟频率,高分辨率意味着计数器可以计更多的数,时钟频率决定了计数的快慢,频率越高,计数速度就越快。
2.数据采集卡的软件配置
一般说来,数据采集卡都有自己的驱动程序,该程序控制采集卡的硬件操作,当然这个驱动程序是由采集卡的供应商提供,用户一般无须通过低层才能与采集卡硬件打交道。
NI 公司还提供了一个数据采集卡的配置工具软件—— Measurement & Automation
Explorer,它可以配置 NI 公司的软件和硬件,比如执行系统测试和诊断、增加新通道和虚拟通道、设置测量系统的方式、察看所连接的设备等。
6.1.7 多通道的采样方式
多数通用采集卡都有多个模入通道,但是并非每个通道配置一个 A/D,而是大家共用一套 A/D,在 A/D 之前的有一个多路开关( MUX),以及放大器( AMP),采样保持器( S/H)
等。通过这个开关的扫描切换,实现多通道的采样。多通道的采样方式有三种:循环采样、
同步采样和间隔采样。在一次扫描( scan)中,数据采集卡将对所有用到的通道进行一次采样,扫描速率( scan rate)是数据采集卡每秒进行扫描的次数。
当对多个通道采样时,循环采样是指采集卡使用多路开关以某一时钟频率将多个通道分别接入 A/D 循环进行采样。如图 6-11 给出两个通道循环采样的示意图。此时,所有的通道共用一个 A/D 和 S/H 等设备,比每个通道分别配一个 A/D 和 S/H 的方式要廉价。循环采样的缺点在于不能对多通道同步采样,通道的扫描速率是由多路开关切换的速率平均分配给每个通道的。因为多路开关要在通道间进行切换,对两个连续通道的采样,采样信号波形会随着时间变化,产生通道间的时间延迟。如果通道间的时间延迟对信号的分析不很重要时,使用循环采样是可以的。
图 6-11 循环采样
当通道间的时间关系很重要时,就需要用到同步采样方式。支持这种方式的数据采集卡每个通道使用独立的放大器和 S/H 电路,经过一个多路开关分别将不同的通道接入 A/D 进行转换。图 6-12 给出两个通道同步采样的示意图。还有一种数据采集卡,每个通道各有一个独立的 A/D,这种数据采集卡的同步性能更好。但是成本显然更高。
图6-12 同步采样
假定用四个通道来采集均为 50kHz 的周期信号(其周期是 20μ s),数据采集卡的采样速率设为 200kHz。则采样间隔为 5μ s( 1/200kHz) 。如果用循环采样则每相邻两个通道之间的采样信号的时间延迟为 5μ s( 1/200kHz),这样通道 1 和通道2之间就产生了 1/4 周期的相位延迟,而通道 1 和通道4之间的信号延迟就达 15μ s,折合相位差是 270
0
。一般说来这是不行的。
为了改善这种情况。而又不必付出像同步采用采样那样大的代价。就有了如下的间隔扫描( interval scanning)方式。
在这种方式下,用通道时钟控制通道间的时间间隔,而用另一个扫描时钟控制两次扫描过程之间的间隔。通道间的间隔由实际上由采集卡的最高采样速率决定,可能是微秒、甚至纳秒级的,效果接近于同步扫描。间隔扫描适合缓慢变化的信号,比如温度和压力。假定一个 10 通道温度信号的采集系统,用间隔采样,设置相邻通道间的扫描间隔为 5μ s,每两次扫描过程的间隔是 1s,这种方法提供了一个以 1Hz 同步扫描 10 通道的方法,如图6 -13所示。 1 通道和 10 通道扫描间隔是 45μ s,相对于 1Hz 的采样频率是可被忽略的。对一般采集系统来说,间隔采样是性价比较高的一种采样方式。
图6-13 间隔采样
NI 公司的数据采集卡可以使用内部时钟来设置扫描速率和通道间的时间间隔。多数数据采集卡根据通道时钟( channel clock )按顺序扫描不同的通道,控制一次扫描过程中相邻通道间的时间间隔,而用扫描时钟( scan clock)来控制两次扫描过程的间隔。通道时钟要比扫描时钟快,通道时钟速率越快,在每次扫描过程中相邻通道间的时间间隔就越小。
对于具有扫描时钟和通道时钟的数据采集卡,可以通过把扫描速率( scan rate)设为 0,
使用 AI Config VI 的 interchannel delay 端口来设置循环采样速率。 LabVIEW 默认的是 scan
clock,换句话来说,当选择好扫描速率时,LabVIEW 自动选择尽可能快的通道时钟速率,
大多数情况下,这是一种比较好的选择。图 6-14 说明循环采样和间隔采样的不同。
图 6-14 间隔采样与循环采样比较
6.1.8 LabVIEW 数据采集模块的分类
LabVIEW 中对于数据采集模块按照难易程度做了分类,图 6-15 以模入为例表明了工具栏中各种类型的模入模块。
图 6-15 模入的各种模块
简易模入 VIs (Ease Analog VIs)
该行的四个模块执行简单的模入操作。它们可以作为单独的 VI,也可以作为 subVI 来使用。这些模块可以自动发出错误警告信息,在对话框中你可以选择中断运行或忽略。但是比较复杂的应用需要使用下面的类型。
中级模入 VIs (Intermediate Analog Input VIs)
中级模入在两个地方可以找到,一个如图 6-15 的位置,另一个是包含在下面讨论的通用模入 VIs 中。与简易模入不同的是在那里的一个操作 AI Input,这里细分为 AI Config,AI
Start,AI Read,AI Single Scan 以及 AI Clear。它可以描述更加细致、复杂的操作。
通用模入 VIs ( Analog Input Utility VIs)
这里提供了三个常用的 Vis,AI Read One Scan,AI Waveform Scan,及 AI Continuous
Scan。使用一个 VI 就可以解决一个普通的模入问题,方便但缺乏灵活性。这三个 Vis 是由中级模入构成的。
高级模入 VIs ( Advanced Analog Input VIs)
这些 Vis 是 NI-DAQ 数据采集软件的界面,是上面三种类型 Vis 的基础。一般情况下,
用户不需要直接使用这个功能。
在下面的介绍中我们主要涉及前两项。
6.2 模拟输入( Analog Input)
6.2.1 模入参数说明
为了更好地理解模入,需要了解信号数字化过程中分辨率、范围、增益等参数对采集信号质量的影响。
分辨率( Resolution)
分辨率就是用来进行模数转换的位数,A/D 的位数越多,分辨率就越高,可区分的最小电压就越小。分辨率要足够高,数字化信号才能有足够的电压分辨能力,才能比较好的恢复原始信号。目前分辨率为 8 的采集卡属于较低的,12 位属中档,16位的卡就比较高了。
他们可以分别将模入电压量化为 256,4096,65536 份。
电压范围 (Range)
电压范围由 A/D 能数字化的模拟信号的最高和最低的电压决定。一般情况下,采集卡的电压范围是可调的,所以可选择和信号电压变化范围相匹配的电压范围以充分利用分辨率简易模入 VIs
中级模入 VIs
高级模入 VIs
通用模入 VIs
范围,得到更高的精度。比如,对于一个 3 位的 A/D,在选择 0-10V 范围时,它将 10V 八等分;如果选择范围为 -10V 到 +10V,同一个 A/D 就得将 20V 分为 8 等分,能分辨的最小电压就从 1.25V 上升到 2.50V,这样信号复原的效果就更差了。
增益( Gain)
增益主要用于在信号数字化之前对衰减的信号进行放大。使用增益,可以等效地降低
A/D 的输入范围,使它能尽量将信号分为更多的等份,基本达到满量程,这样可以更好地复原信号。因为对同样的电压输入范围,大信号的量化误差小,而小信号时量化误差大。当输入信号不接近满量程时,量化误差会相对加大。如:输入只为满量程的 1/ 10 时,量化误差相应扩大 10 倍。一般使用时,要通过选择合适的增益,使得输入信号动态范围与 A/D 的电压范围相适应。当信号的最大电压加上增益后超过了板卡的最大电压,超出部分将被截断而读出错误的数据。
对于 NI 公司的采集卡选择增益是在 LabVIEW 中通过设置信号输入限制( input limits)
来实现的,LabVIEW 会根据选择的输入限制和输入电压范围的大小来自动选择增益的大小。
一个采集卡的分辨率、范围和增益决定了可分辨的最小电压,它表示为 1LSB。例如,
某采集卡的分辨率为 12 位,范围取 0-10V,增益取 100,则有 1LSB=10V/ (100× 4096)≈24
μ V。这样,在数字化过程中,最小能分辨的电压就为 24μ s。
选择合适的增益和输入范围要与实际被测信号匹配。 如果输入信号的改变量比采集卡的精度低,就可以将信号放大,提高增益。选择一个大的输入范围或降低增益可以测量大范围的信号,但这是以精度的降低为代价的。选择一个小的输入范围或提高增益可以提高精度,
但这可能会使信号超出 A/D 允许的电压范围。
在研究采集 VI 之前需要了解如下的几个定义。我们以下图的多通道模入波形采集 AI
Acquire Waveform.vi 为例说明。
device——设备号。在 NI 采集设置工具中设定。该参数告诉 LabVIEW 你使用什么卡,
它可以使采集 VI 自身独立于卡的类型,也就是说,如果你稍后使用了另一种卡,并且赋予它同样的设备号,你的 VI 程序可正常工作而无须修改。
channels——指定数据样本的物理源。例如,一个卡有16个模拟输入 通道,你就可以同时采集16组数据点。在 LabVIEW VI 中,一个 通道 或一组 通道 都用一个字符串来指定。例如,
通道 通道串
通道 5 5
通道 0 到 4 0:4
通道 1,8,以及 10 到 13 1,8,10:13
scan rate(1000 scans/sec)——是在多通道采样时,分配给一个通道得到的样本速率,
缺省值是 1000/秒。
number of samples/ch——每通道要采集的样本数,缺省值是 1000。
high limit——被测信号的最高电平,其缺省值是0。设为缺省值时系统将按照采集卡设置程序 MAX 中的设定处理。
low limit——被测信号的最低电平,其缺省值是0。设为缺省值时系统将按照采集卡设置程序 MAX 中的设定处理。
high limit 和 low limit 的值将决定采集系统的增益。对大多数卡输入信号变化的缺省值是 10V 到 -10V,如果你将其设为 5 到 -5V,则增益为 2。如果你将其设为 1 到 -1V,
则增益为 10。如果你设置一个理论上的增益是得不到支持的,LabVIEW 会自动将其调整到最近的预置值。典型的采集卡所支持的增益值有 0.5,1,2,5,10,20,50,100。
waveforms—— A/D 转换后的输出,是一个二维的 waveform 数组,其每一列对应于一个输入通道,同时包含有反映时间信息的 t0 和Δ t。
LabVIEW 数据采集模块的分类
下面我们将由简到难地介绍有关内容。
6.2.2 简易模入( Ease Analog VIs)
这是 LabVIEW 提供的一组标准的、简单易用的采集 VI。
从左到右,4个 VI 的功能为,
null 从指定通道获得一个样本。
null 从由通道字符串规定的一组通道每通道获得一个样本。 这些样本返回到一个样本数组,顺序由通道号决定。
null 按指定的采样率由一个通道得到一个波形(一组覆盖一个周期的样本),这些样本返回到一个 wareform 数组。
null 从由通道字符串规定的每个通道获得一个波形。 这些样本返回到一个波形的2维数组,顺序由通道号和采样周期决定。 通道数据的每个点占1列,时间增量由行决定。
练习 6-1
目的:采集一个直流电压信号
1.00.0
0.2
0.4 0.6
0.8
Meter
Meter
0
1
1.准备一个直流电源(例如 0.5V)作为信号源连接到数据采集卡的 0 通道模入端。
2.构造前面板和框图如上面所示。
3.运行程序。可得到 Meter 指示 0.5V。
练习 6-1 结束
练习 6-2
目的:多通道数据采集
1.准备一个方波信号源和一个正弦波信号源。分别连接到模入通道0和1。
2.设置前面板与框图如上。
3.设置 scan 速率、通道号、每通道样本数如前面板所示。
4.运行该程序。
5.保存为 Acquire Multiple Channels.vi。
6.该程序是无缓冲、软件触发的。
注意:这里使用的 AI Acquire Waveform.vi 具有多态性,它的输出可以是 Waveform,也可以是 Array,前者可直接与 Graph 连接,后者如果直接要与 Graph 连接麻烦一些。 在 LabVIEW
6I 以前的版本中只有后者。用后者编写这个程序的框图如下,
增加的步骤包括,
7.在框图上调出 AI Acquire Waveform.vi 的快速菜单,选择 Select Type >Scaled Array。
8.在前面板上的 graph 上用快捷菜单选择 Transpose Array。因为 AI Sample Channel
功能返回的 2D 数组是每列反映一个通道的电压,而在一般情况下 graph 图形是行对列,所以需要对数组做一次转置,以使 Y 轴表示电压值。
9.在框图上将起始时刻、实际采样周期的倒数和采样数据使用 Bundle 功能捆绑成一个数组,送给 graph。注意捆绑的顺序是 I32,SGL 和数组,如果变为 I32、数组和 SGL,可能出错。
练习 6-2 结束
6.2.3 中级模入 Analog Input
上面介绍的简单模入的基本局限是执行采集任务的庸余。例如,你每一次调用 AI
Sample Channel,都必须为特定类型的测量设置硬件,告诉它采样率等。显然,如果你要反复采集大量的样本,你未必需要在每一次重复时都去设置测量。 一个典型的情况是连续采集,
需要在程序中采用循环结构,按照简单模入,每次采集前都在设置参数,不仅多余,而且造
0
扫描速率每通道样本数
Waveform Graph
AI Acquire Waveforms.vi
成了采集过程的不连续。
中级模入有更好的功能与灵活性,可以更有效地开发你的应用。它的特点包括控制内部采样率,使用外部触发,执行连续外部触发等。下面我们将仔细描述它的各种 VI,应该注意其大量输入、输出端子中的部分内容一般是不必理会的。有效地使用这些 VI 只需要关注你需要的端子。在大多数情况下,你不需要为在 help 中解释的端子的设置烦恼。
null Analog Input
AI Config 对指定的通道设置模入操作,包括硬件、计算机内 buffer 的分配。常用的端子有,
null Device——采集卡的设备号。
null Channel——指定模入通道号的串数组。
null Intput limit——指定输入信号的范围达到调节硬件增益的目的。
null Buffer size——单位是 scan,控制用于采集数据的 AI Config 占用计算机内存的大小。
null Interchannel delay——扫描间隔设置。缺省值为 -1,当选用缺省值时,系统按照采集卡的最高扫描速率(一般为几微秒),再加上系统消耗 10 微秒,来设置扫描间隔,对 MIO-16-E-4 卡来说,约为 14 微秒。用户也可以自行设置这个值,实验表明,
对 MIO-16-E-4 卡最小可设到 2~3 微秒。
AI Start 启动带缓冲的模入操作。它控制数据采集速率,采集点的数目,及使用任何硬件触发的选择。它的两个重要输入是,
null Scan rate(scan/sec)——对每个通道采集的每秒扫描次数。
null Number of scans to acquire——对通道列表的扫描次数。??
AI Read——从被 AI Config 分配的缓冲读取数据。它能够控制由缓冲读取的点数,读取数据在缓冲中的位置,以及是否返回二进制数或标度的电压数。 它的输出是一个2维数组,
其中每一列数据对应于通道列表中的一个通道。
AI Single Scan——返回一个扫描数据。它的电压数据输出是由通道列表中的每个通道读出的电压数据。使用这个 VI 仅与 AI Config 有关联,不需要 AI Start 和 AI Read。
AI Clear——清除模入操作、计算机中分配的缓冲、释放所有数据采集卡的资源,例如计数器。
当你设置一个模入应用时,首先使用的 VI总是 AI Config。 AI Config会产生一个 taskID
和 Error cluster(出错信息簇) 。所有别的模入 VI 接受这个 taskID 以识别操作的设备和通道,并且在操作完成后输出一个 taskID。因为 taskID 是一个输入并向另一个模入 VI 输出,所以该参数形成了采集 VI 之间的一个关联数据。
练习 6-3
目的:多通道波形的连续采集
现在我们使用 LabVIEW 提供的 DAQ 向导来搭建这个程序,操作步骤如下,
1.选 LabVIEW 进入画面选择 DAQ Solutions
2.进入 Welcome to the Solution Wizard 选
null Program the input scaling and conversion myself
3.进入 Solution Wizard –Step 2 to 3 选
null Custom DAQ Applications
4.进入 Solution Wizard –Step 3 to 3 选
null Analog Input
5.进入 Analog Input Functionality 选
在 Step 1 中选择0、1两个通道
在 Step 2 中选择 Scan multiple sample from each channel continuously
点击 OK 按钮
6.又回到 Solution Wizard –Step 3 to 3,显示选中的各种配置,点击[ Open Solution]按
钮,可以看到形成的程序。
上面的面板和框图略做了简化,删去了有关错误信息处理的一个模块。在这个程序中有几个问题值得注意
1.在 AI Config 中设置 interchannel delay 为 –1,使用间隔扫描方式,避免了通道延迟。
2.在这个简化了的框图上我们可以更加清晰地看出中级模入的处理框图,大致如下,
图 6-16 连续采集程序模型
无疑,这个流程更加合理,它把采集的初始化与结束处理放在了循环之外。
1
device (1)
STOP
5.0
-5.0
-4.0
-2.0
0.0
2.0
4.0
3599934999 35200 35400 35600 35800
transposed waveform chart
10000.00
scan rate
(1000 scans/sec)
4000
buffer size
(4000 scans)
2000
scans to read
at a time (1000)
2
scan backlog
hardware settings
-1.00
interchannel delay
in secs ( -1,hw default)
0.00
high li
0.00
low lim
0
input limits
0:1
0
channels (0)
channels (0)
input limits
interchannel delay
in secs ( -1,hw default)
0
buffer size
(4000 scans)
scan rate
(1000 scans/sec)
transposed waveform chart
scans to read
at a time (1000)
scan backlog
Read & chart data until an error
occurs,or the stop button pressed.
0
continuous
acquisition
device (1)
3,Buffer 的设置和使用,连续采集时通常需要 Buffer。 面板上有3个与 Buffer 有关的对象。
其一是 Buffer Size(单位,scan 的个数 ),这是它的大小,其二是 Scans to Read at a time,
即每一次从 Buffer 中读走的 scan 的个数,其三是 scan backlog,这里显示在 Buffer 中积压的 scan 个数。这个数的大小取决于系统的运行速度。只要这里显示一个大于 Buffer
Size 的数,系统将出错,中断运行。
这里使用的是一种称为循环 Buffer 机制。其原理如下:在往缓冲区中放数据的
同时可以读取缓冲区中已放的数据,当缓冲区满时,从缓冲区开始处重新存放新的数
据,只要放数据和取数据的速度配合好,就可以实现用一块有限的存储区,来进行连
续的数据传送。使用循环缓冲区,可以在采集设备在后台连续进行采集的同时,
LabVIEW 在两次读取缓冲区数据的时间间隔里对数据进行处理。循环缓冲区 存取数据
说明如图 6-17 所示。
图 6-17 循环缓冲区存取数据说明
程序读取数据的速度要不慢于采集设备往缓冲区中放数据的速度,才能保证连续运行时,缓冲区中的数据不会溢出,不会丢数据。如果程序取数据的速度快于放数据的速度,LabVIEW 会等待数据放好后再读取。如果程序读取数据的速度慢于放数据的速度,
LabVIEW 发送一个错误信息,告诉用户有一些数据可能被覆盖并丢失。可以通过调整三个参数来解决这个问题,input buffer size,scan rate 和 number of scans to read at a time。
增大 input buffer size 可以延长填满缓冲区的时间,但是这不能根本上解决连续采集过程中数据被覆盖的问题,要根本解决这个问题,需要减小 scan rate 或者增大 number of scans
to read at a time。 number of scans to read at a time 一般设置为一个小于缓冲区大小的值,
缓冲区大小一般设置为 scan rate 的两倍。具体的设置需要通过测试整个采集程序运行的情况来确定。 可以通过查看输出端的 scan backlog 的大小判断缓冲中数据会不会被覆盖,
scan backlog 被定义为从采集缓存中采集到而不是读到的扫描个数,是一个衡量系统是否跟得上连续采集数据的一个量度,如果 scan backlog 的数值一直在上升则表明从缓存中读数据的速度不够快并且最终会丢失数据,如果丢失数据,AI Read VI 将会给出错误提示。
练习 6-3 结束
6.3 模出( Analog Output)
6.3.1 基本参数与术语
多功能的 DAQ 卡用数模转换器( D/A)将数字信号转换成模拟信号,D/A 的有关参数有范围( Range),分辨率( Resolution),单调性( Monotonicity),线性误差 (Linearity Error)、
建立时间 (Settling Time)、转换速率( Slew Rate),精度( Accuracy)等。下面对部分参数做一些解释。
建立时间 (Settling Time),是指变化量为满刻度时,达到终值 1/2LSB 时所需的时间。这个参数反映 D/A 的 D/A 转换从一个稳态值到另一个稳态值的过渡过程的长短。建立时间一般为几十纳秒至几微秒。
转换速率 (Slew Rate),是指 D/A 输出能达到的最大变化速率,即电平变化除以转换所用时间,通常指电压满范围内的转换速率。
精度( Accuracy),分为绝对精度和相对精度。绝对精度是指输入某已知数字量时其理论输出模拟值和实际所测得的输出值之差,该误差一般应低于 1/2LSB。相对精度是绝对精度相对于额定满度输出值的比值,可用偏差多少 LSB 或者相对满度的百分比表示。 D/A 的分辨率越高,数字电平的个数就越多,精度越高。 D/A 范围增大,精度就会下降。
由建立时间和转换速度可以得到 D/A 转换输出信号电平的快慢。一个有着更小的建立时间和更高的转换速率的 D/A 可以产生更高的输出信号频率,因为它达到新的电平所需的时间更少。
图 6-18 Settling Time 和 Slew Rate
6.3.2 简易模出 (Easy Analog Output)
与简易模入类似,这里也提供了4个模块,分别对应于单(多)通道输出波形或电压数据。下面我们通过练习来讨论
练习 6-4
目的:产生一个模出电平
1
device
3.00
value to generate
10.0
0.0
2.0
4.0 6.0
8.0
data output meter
0
channel
做面板及框图如上。运行该程序,可以看到表的输出将指示3。这个指示并非模出,为了看到模出,可以使用一块数字万用表直接测量 DAC0 OUT。你会发现万用表的指示一直维持在3 V,尽管程序早已执行完了。
练习 6-4 结束
练习 6-5
目的:产生一个模出波形
做面板及框图如上。框图中我们首先产生一个正弦波形(其初相位可控),然后将它送给模出,同时连接到一个 Graph 显示。运行该程序,可以使用一块数字万用表的直流电压档直接测量 DAC0 OUT。你会发现当初相位为0时,万用表的指示是0,当初相位为 90 度时,
万用表的指示是 1。这表明该程序输出的不是一个连续不断的波形,仅仅是一个或若干个整周期的波形。模出模块在结束操作后并没有清0复位,一直维持在最后一刻的电平上。如果希望产生一个连续不断的波形,需要使用下面的较复杂的中级函数模块。
练习 6-5 结束
6.3.3 中级模出( Analog Output)
AO Config 对指定的通道设置模出操作,包括硬件、计算机内 buffer 的分配。常用的端子有,
null Device——采集卡的设备号。
null Channel——指定模出通道号的串数组。
null Limit settings——指定输出信号的范围。
null taskID——用于所有后来的模出 VI 以规定操作的设备和通道。
AO Write 以电压数据的方式写数据到模出数据缓冲区。它是一个2维数组,其中每一列数据对应于通道列表中的一个通道。注意:通常其他函数为其准备的波形数据是一个1维数组,且数据分布在一行中,这里需要将其“虚扩”为二维数组,并做一次转置。
AO Start 启动带缓冲的模出操作。 Update rate(scan/sec)是每秒发生的更新数的个数。
如果你将0写入 Number of buffer iteerations 端子,则卡将连续输出给缓冲,直到运行
AO Clear 功能。
AO Wait 在返回之前一直等待直到波形发生任务完成。它的电压数据输出是由通道列表中的每个通道读出的电压数据。使用这个 VI 仅与 AO Config 有关联,不需要 AO Start 和
AO Read。
AO Clear——清除模出操作、计算机中分配的缓冲、释放所有数据采集卡的资源,例如计数器。
当你设置一个模出应用时,首先使用的 VI 总是 AO Config。 AO Config 会产生一个 taskID
和 Error cluster(出错信息簇) 。所有别的模出 VI 接受这个 taskID 以识别操作的设备和通道,并且在操作完成后输出一个 taskID。该参数形成了采集 VI 之间的一个关联数据。
练习 6-6
目的:产生一个连续的正弦信号(1)
做面板及框图如下。
2
update rate (1000 updates/sec)
0
Y
Waveform Graph
frequency
buffer size (1000 updates)
status
stop
上面的框图中需要说明以下几点,
由于 AO Write 要求输入数据的要求(见上文),这里正弦波发生器的输出是一个
waveform 数据类型,首先将其中的 Y 数据提出,然后将它扩充为一个二维数组,再经转置后才可连接到 AO Write 。
在 AO Config 中主要是设置了 Buffer,这对于连续输出是必须的,其它都选默认值。
Buffer 的大小有时需要经过调试,过大或过小都可能导致不能正常工作。
练习 6-6 结束
练习 6-7
目的:产生一个连续的正弦信号(2)
下面我们使用 Analog Output Utilities 下提供的连续模出的现成模块再做一个连续的正弦信号发生器。面板与框图如下所示,
该例子中开关是控制 AO C-GEN 内部的 AO Clear 模块。当其状态为 T 时,运行程序将释放计算机及采集卡资源,无信号输出。
在程序框图上点击 AO C-GEN 图标,可以看到其内部结构。
练习 6-7 结束
sampling info
frequency
clear generation
5.00
Y
dt
t0
第七章 信号处理与分析
7.1 概述
数字信号在我们周围无所不在。因为数字信号具有高保真、低噪声和便于信号处理的优点,所以得到了广泛的应用,例如电话公司使用数字信号传输语音,广播、电视和高保真音响系统也都在逐渐数字化。太空中的卫星将测得数据以数字信号的形式发送到地面接收站。
对遥远星球和外部空间拍摄的照片也是采用数字方法处理,去除干扰,获得有用的信息。经济数据、人口普查结果、股票市场价格都可以采用数字信号的形式获得。因为数字信号处理具有这么多优点,在用计算机对模拟信号进行处理之前也常把它们先转换成数字信号。本章将介绍数字信号处理的基本知识,并介绍由上百个数字信号处理和分析的 VI 构成的
LabVIEW 分析软件库。
目前,对于实时分析系统,高速浮点运算和数字信号处理已经变得越来越重要。这些系统被广泛应用到生物医学数据处理、语音识别、数字音频和图像处理等各种领域。数据分析的重要性在于,无法从刚刚采集的数据立刻得到有用的信息,如下图所示。必须消除噪音干扰、纠正设备故障而破坏的数据,或者补偿环境影响,如温度和湿度等。
通过分析和处理数字信号,可以从噪声中分离出有用的信息,并用比原始数据更全面的表格显示这些信息。下图显示的是经过处理的数据曲线。
用于测量的虚拟仪器 (VI)
用于测量的虚拟仪器 (VI)执行的典型的测量任务有,
null 计算信号中存在的总的谐波失真。
null 决定系统的脉冲响应或传递函数。
null 估计系统的动态响应参数,例如上升时间、超调量等等。
null 计算信号的幅频特性和相频特性。
null 估计信号中含有的交流成分和直流成分。
在过去,这些计算工作需要通过特定的实验工作台来进行,而用于测量的虚拟仪器可以使这些测量工作通过 LabVIEW 程序语言在台式机上进行。这些用于测量的虚拟仪器是建立在数据采集和数字信号处理的基础之上,有如下的特性,
null 输入的时域信号被假定为实数值。
null 输出数据中包含大小、相位,并且用合适的单位进行了刻度,可用来直接进行图形的绘制。
null 计算出来的频谱是单边的( single_sided),范围从直流分量到 Nyquist 频率 (二分之一取样频率 )。 (即没有负频率出现)
null 需要时可以使用窗函数,窗是经过刻度地,因此每个窗提供相同的频谱幅度峰值,可以精确地限制信号的幅值。
一般情况下,可以将数据采集 VI 的输出直接连接到测量 VI 的输入端。测量 VI 的输出又可以连接到绘图 VI 以得到可视的显示。
有些测量 VI 用来进行时域到频域的转换,例如计算幅频特性和相频特性、功率谱、网路的传递函数等等。另一些测量 VI 可以刻度时域窗和对功率和频率进行估算。
本章我们将介绍测量 VI 中常用的一些数字信号处理函数。
LabVIEW 的流程图编程方法和分析 VI 库的扩展工具箱使得分析软件的开发变得更加简单。 LabVIEW 分析 VI 通过一些可以互相连接的 VI,提供了最先进的数据分析技术。你不必像在普通编程语言中那样关心分析步骤的具体细节,而可以集中注意力解决信号处理与分析方面的问题。 LabVIEW 6i 版本中,有两个子模板涉及信号处理和数学,分别是 Analyze
子模板和 Methematics 子模板。这里主要涉及前者。
进入 Functions 模板 Analyze,Signal Processing 子模板。
其中共有 6 个分析 VI 库。其中包括,
①,Signal Generation(信号发生),用于产生数字特性曲线和波形。
②,Time Domain(时域分析),用于进行频域转换、频域分析等。
③,Frequency Domain(频域分析),
④,Measurement(测量函数),用于执行各种测量功能,例如单边 FFT,频谱、比例加窗以及泄漏频谱、能量的估算。
⑤,Digital Filters(数字滤波器),用于执行 IIR,FIR 和非线性滤波功能。
⑥,Windowing(窗函数),用于对数据加窗。
在后面几节中,你将学习如何使用分析库中的 VI 创建函数发生器和简单实用的频谱分析仪,如何使用数字滤波器,窗函数的作用以及不同类型窗函数的优点,怎样执行简单的曲线拟合功能,以及其他一些内容。可以在 labview\examples\analysis 目录中找到一些演示程序。
7.2 信号的产生
本节将介绍怎样产生标准频率的信号,以及怎样创建模拟函数发生器。参考例子见
examples\analysis\sigxmpl.llb。
你还将学习怎样使用分析库中的信号发生 VI 产生各种类型的信号。信号产生的应用主要有,
null 当无法获得实际信号时,(例如没有 DAQ 板卡来获得实际信号或者受限制无法访问实际信号),信号发生功能可以产生模拟信号测试程序。
null 产生用于 D/A 转换的信号
在 LabVIEW 6i 中提供了波形函数,为制作函数发生器提供了方便。以
Waveform>>Waveform Generation 中的基本函数发生器( Basic Function Generator.vi)为例,
其图标如下,
其功能是建立一个输出波形,该波形类型有:正弦波、三角波、锯齿波和方波。这个 VI 会记住产生的前一波形的时间标志并且由此点开始使时间标志连续增长。 它的输入参数有波形类型、样本数、起始相位、波形频率(单位,Hz)
参数说明,
offset,波形的直流偏移量,缺省值为 0.0。数据类型 DBL
reset signal,将波形相位重置为相位控制值且将时间标志置为 0。缺省值为 FALSE,
signal type,产生的波形的类型,缺省值为正弦波。
frequency,波形频率(单位 Hz),缺省值为 10。
amplitude,波形幅值,也称为峰值电压,缺省值为 1.0。
phase,波形的初始相位(单位 度)缺省值为 0.0,
error in,在该 VI 运行之前描述错误环境。缺省值为 no error,如果一个错误已经发生,该
VI 在 error out 端返回错误代码。该 VI 仅在无错误时正常运行。 错误簇包含如下参数。
status,缺省值为 FALSE,发生错误时变为 TRUE。
code,错误代码,缺省值为 0。
source,在大多数情况下是产生错误的 VI 或函数的名称,缺省值为一个空串。
sampling info,一个包括采样信息的簇。共有 Fs 和 #s 两个参数。
Fs,采样率,单位是样本数 /秒,缺省值为 1000。
#s,波形的样本数,缺省值为 1000。
duty cycle (%),占空比,对方波信号是反映一个周期内高低电平所占的比例,缺省值为 50%。
signal out:信号输出端
phase out,波形的相位,单位:度。
error out,错误信息。如果 error in 指示一个错误,error out 包含同样的错误信息。否则,
它描述该 VI 引起的错误状态。
使用该 VI 制作的函数发生器如下,由框图可以看出,其中没有附加任何其他部件。
7.3 标准频率
在模拟状态下,信号频率用 Hz 或者每秒周期数为单位。但是在数字系统中,通常使用数字频率,它是模拟频率和采样频率的比值,表达式如下,
数字频率=模拟频率 /采样频率
这种数字频率被称为标准频率,单位是周期数 /采样点。
z 有些信号发生 VI 使用输入频率控制量 f,它的单位和标准频率的单位相同:周期数 /
每个采样点,范围从 0 到 1,对应实际频率中的 0 到采样频率 fs 的全部频率。它还以 1.0 为周期,从而令标准频率中的 1.1 与 0.1 相等。 例如某个信号的采样频率是奈奎斯特频率 ( fs/2),
就表示每半个周期采样一次(也就是每个周期采样两次) 。与之对应的标准频率是 1/2 周期数 /采样点,也就是 0.5 周期数 /采样点。标准频率的倒数 1/f 表示一个周期内采样的次数。
如果你所使用的 VI 需要以标准频率作为输入,就必须把频率单位转换为标准单位:周期数 /采样点。
7.4 数字信号处理
7.4.1 FFT 变换
信号的时域显示(采样点的幅值)可以通过离散傅立叶变换( DFT)的方法转换为频域显示。为了快速计算 DFT,通常采用一种快速傅立叶变换 (FFT)的方法。当信号的采样点数是 2 的幂时,就可以采用这种方法。
FFT 的输出都是双边的,它同时显示了正负频率的信息。通过只使用一半 FFT 输出采样点转换成单边 FFT。 FFT 的采样点之间的频率间隔是 fs/N,这里 fs 是采样频率。
Analyze 库中有两个可以进行 FFT 的 VI,分别是 Real FFT VI 和 Complex FFT VI。
这两个 VI 之间的区别在于,前者用于计算实数信号的 FFT,而后者用于计算复数信号的 FFT。它们的输出都是复数。
大多数实际采集的信号都是实数,因此对于多数应用都使用 Real FFT VI 。当然也可以通过设置信号的虚部为 0,使用 Complex FFT VI 。使用 Complex FFT VI 的一个实例是信号含有实部和虚部。这种信号通常出现在数据通信中,因为这时需要用复指数调制波形。
计算每个 FFT 显示的频率分量的能量的方法是对频率分量的幅值平方。高级分析库中
Power Spectrum VI 可以自动计算能量频谱。 Power Spectrum VI 的输出单位是 Vrms
2
。但是能量频谱不能提供任何相位信息。
FFT 和能量频谱可以用于测量静止或者动态信号的频率信息。 FFT 提供了信号在整个采样期间的平均频率信息。因此,FFT 主要用于固定信号的分析(即信号在采样期间的频率变化不大)或者只需要求取每个频率分量的平均能量。
2.流程图中的 Array Size 函数用来根据样本数转换 FFT 的输出,得到频率分量的正确幅值。
3.把该 VI 保存为 LabVIEW\Activity 目录中的 FFT_2sided.vi。
4.选择频率( Hz) =10,采样率 = 100,样本数 = 100。执行该 VI。注意这时的时域图和频谱图。因为采样率 =样本数 = 100,所以时域图中的正弦波的周期数与选择的频率相等,
即可以显示 10 个周期。 (如果把频率改成 5,那么就会显示 5 个周期)
Y
dt
t0
0
频谱时域信号样本数采样频率频率( HZ)
双边 FFT
5.检查频谱图可以看到有两个波峰,一个位于 10Hz,另一个位于 90Hz,90Hz 处的波峰实际上是 10Hz 处的波峰的负值。因为图形同时显示了正负频率,所以被称为双边 FFT。
6.先后令频率 =10,20( Hz),执行该 VI。注意每种情况下频谱图中波峰位置的移动。
观察频率等于 10 和 20 时的时域波形。注意哪种情况下的波形显示更好,并解释原因。
7.因为 fs = 100 Hz,所有只能采样频率低于 50Hz 的信号(奈奎斯特频率= fs/2) 。把频率修改为 48Hz,可以看到频谱图的波峰位于 ± 48 Hz。
8.把频率改为 52HZ,观察这时产生的图形与第 5 步产生的图形的区别。因为 52 大于奈奎斯特频率,所以混频偏差等于 |100 – 52| = 48 Hz。
9.把频率改成 30 和 70Hz,执行该 VI。观察这两种情况下图形是否相同,并解释原因。
单边 FFT
10.按照下图修改流程图。上面已经知道因为 FFT 含有正负频率的信息,所以可以 FFT
具有重复信息。现在这样修改之后只显示一半的 FFT 采样点(正频率部分) 。这样的方法叫做单边 FFT。单边 FFT 只显示正频部分。注意要把正频分量的幅值乘以 2 才能得到正确的幅值。但是,直流分量保持不变。 (若程序中考虑含直流分量的情况,应当增加一个分支或
case 结构。
2.00
2
Y
dt
t0
0
频谱时域信号序列样本数采样频率频率( HZ)
11.设置频率( Hz) = 30,采样率 = 100,样本数 = 100,运行该 VI。
12.保存该 VI 为 LabVIEW\Activity 目录下的 FFT_1sided.vi。
13.把频率改为 70Hz,执行该 VI,观察这时产生的图形与第 9 步产生的图形的区别。
练习 6-1 结束。
6.4.2 窗函数
计算机只能处理有限长度的信号,原信号 x(t)要以 T(采样时间或采样长度 )截断,即有限化。有限化也称为加“矩形窗”或“不加窗” 。矩形窗将信号突然截断,这在频域造成很宽的附加频率成分,这些附加频率成分在原信号 x(t)中其实是不存在的。一般将这一问题称为有限化带来的泄露问题。泄露使得原来集中在 f
0
上的能量分散到全部频率轴上。泄露带来许多问题:如①使频率曲线产生许多“皱纹” ( Ripple),较大的皱纹可能与小的共振峰值混淆;②如信号为两幅值一大一小频率很接近的正弦波合成,幅值较小的一个信号可能被淹没。③ f
0
附近曲线过于平缓,无法准确确定 f
0
的值。
为了减少泄露,人们尝试用过渡较为缓慢的、非矩形的窗口函数。常用的窗函数如下表所示。
窗 定 义 应 用
矩形窗(无窗)
W[n]=1.0
区分频域和振幅接近的信号瞬时信号宽度小于窗
指数形窗
W[n]=exp[n*lnf/N-1]
f=终值
瞬时信号宽度大于窗
海宁窗 W[n]=0.5cos(2nπ /N) 瞬时信号宽度大于窗普通目的的应用
海明窗 W[n]=0.54-0.46cos(2nπ /N) 声音处理
平顶窗
W[n]=0.2810639-0.5208972cos(
2nπ /N)
+0.1980399cos(2nπ /N)
分析无精确参照物且要求精确测量的信号
Kaiser-Bessel 窗 W[n]=Io (β ) 区分频率接近而形状不同的信号三角形窗 W[n]=1-|( 2n-N) /N| 无特殊应用
在实际应用中如何选择窗函数一般说来是要仔细分析信号的特征以及最终你希望达到的目的,并经反复调试。窗函数有利有弊,使用不当还会带来坏处。使用窗函数的原因很多,
例如,
null 规定测量的持续时间。
null 减少频谱泄漏。
null 从频率接近的信号中分离出幅值不同的信号。
下面的例子(详见 LabVIEW 6i 中的 Search Examples > Fundamentals Examples
>Analysis Examples > Signal Processing > Windows Examples > Window Comparison)是从频率接近的信号中分离出幅值不同的信号,正弦波1与正弦波2频率较接近,但幅值相差
1000 倍,相加后产生的信号变换到频域,如果在 FFT 之前不加窗,则 频域特性中幅值较小的信号被淹没。加 Hanning 窗后两个频率成分都被检出。
1.0
-1.0
-0.5
0.0
0.5
990 10 20 30 40 50 60 70 80 90
Time Domain
0
-140
-120
-100
-80
-60
-40
-20
2550 50 100 150 200
None
Hanning
频域特性不同类型窗口函数在频域的效果。不使用窗口函数时,幅值较小的正弦波 1被淹没。
使用 Hanning窗口函数后 (Window 2),幅值较小的正弦波 1被发现。
Stop
100.0
0.0
20.0
40.0 60.0
80.0
73.92频率 1
正弦波形 1 正弦波形 2
正弦波形 1 +正弦波形 2
0.001
幅值 1
1.000
幅值 2
100.0
0.0
20.0
40.0 60.0
80.0
59.24
频率 2
dB
None
Window 1
Hanning
Window 2
7.4.3 谐波失真与频谱分析
当一个含有单一频率 (比如 f
1
)的信号 x(t)通过一个非线性系统时,系统的输出不仅包含输入信号的频率( f
1
),而且包含谐波分量( f
2
=2f
1
,f
3
=3f
1
,f
4
=4f
1
等等),谐波的数量以及它们对应的幅值大小取决于系统的非线性程度。电网中的谐波是一个值得关注的问题。
下面的一个非线性系统的例子是输出 y(t)是输入 x(t)的立方。假如输入信号,
)cos()( wttx =
则输出,
)]3cos()[cos(25.0)cos(5.0)(
3
wtwtwttx ++=
因此,输出不仅含有基波频率 w,而且还有三次谐波的频率 3w。
谐波失真的总量
为了决定一个系统引入非线性失真的大小,需要得到系统引入的谐波分量的幅值和基波的幅值的关系。谐波失真是谐波分量的幅值和基波幅值的相对量。假如基波的幅值是 A
1
,
而二次谐波的幅值是 A
2
,三次谐波的幅值是 A
3
,四次谐波的幅值是 A
4
。 。 。 。 。 。 N 次谐波的幅值是 A
N
,总的谐波失真( THD)为,
1
22
3
2
2
...
A
AAA
N
THD
++
=
用百分数表示的谐波失真( %THD)为,
1
22
3
2
2
...*100
%
A
AAA
N
THD
++
=
LabVIEW 6i 提供的谐波分析器与以前的版本有一些变化,下面先介绍它
该 VI 对输入信号进行完整的谐波分析,包括测定基波和谐波,返回基波频率和所有的谐波幅度电平,以及总的谐波失真度( THD) 。其部分参数含义如下,
stop search at Nyquist:如果设置为 TRUE (缺省值 T),则只包含低于 Nyquist 频率(采样频率的一半)的谐波。如果设置为 FALSE,该 VI 将继续搜索 Nyquist 范围之外的频率。
signal in,输入信号。
export signals,选择输出到信号指示器的信号。有如下几种选择,
none——对快速计算;
input signal——定时将输入信号反映到输出端;
fundamental signal——在输出端反映基波;
residual signal——在输出端反映除基波之外的剩余信号;
harmonics only——在输出端反映谐波时域信号及其频谱。
highest harmonic,控制最高谐波成分,包括用于谐波分析的基波。例如,对于 3 次谐波分析,该控制将设置测量基波,2 次谐波和 3 次谐波。,
error in,在该 VI 运行之前描述错误环境。缺省值为 no error,如果一个错误发生,该 VI
在 error out 端返回错误代码。该 VI 仅在无错误时正常运行。 错误簇包含如下参数。
status,缺省值为 FALSE,发生错误时变为 TRUE。
code,错误代码,缺省值为 0。
source,在大多数情况下是产生错误的 VI 或函数的名称,缺省值为一个空串。
advanced search,控制频域搜索区域,中心频率及频带宽度。该功能用来确定信号的基波。
approx,fund,freq,(optional) ——用来搜索基波的中心频率的估算值。 如果设置缺省值为 -1.0,,则选择幅值最大的频率成分为基波。
search (+/- % of Fsampl.) ——用来搜索基波频率频带宽度,是采样率的百分比。
exported signals,包含输出的时域信号及其频谱供选择。
detected fundamental frequency,探测在频域搜索得到的基波。用 advanced search 设置频率搜索范围。所有谐波测量为基波的整数倍。
THD,总谐波失真度。它定义为谐波 RMS 之和与基波幅值之比。为了折算为百分数,需要乘以 100。
components level,测量谐波幅值的电平(单位 伏),是一个数组。该数组索引包括 0 (DC),
1 (基波 ),2 (2 次谐波 ),..,n (n 次谐波 ),直到最高谐波成分。
measurement info cluster,任何处理期间遭遇的预告
uncertainty 备用;
Warning,如果处理期间警告发生为 TRUE。
comments,当 Warning 为 TRUE 时的消息内容。
下面是一个谐波分析的例子。由通道 0 输入一个模拟信号,经 DAQ 后进行谐波分析,
先后分析了两个信号,首先是一个 761Hz 的正弦信号,第二个信号是一个 1000Hz 的。分析仅限于不高于 5 次的谐波。分析结果见两个前面板。对一个实际的正弦信号,谐波失真总量
( THD)与基波电平相比,可以忽略。对方波 THD 就较大了。
谐波分析应用的一个例子
6.3.1 数字滤波
模拟滤波器设计是电子设计中最重要的部分之一。 尽管很多参考书都提供了简单可靠的模拟滤波器示例,但是滤波器的设计通常还是需要专家来完成,因为这项工作需要较高深的数学知识和对系统与滤波器之间的关系有深入的了解。
现代的数字采样和信号处理技术已经可以取代模拟滤波器,
尤其在一些需要灵活性和编程能力的领域中,例如音频、通讯、
地球物理和医疗监控技术。
与模拟滤波器相比,数字滤波器具有下列优点,
null 可以用软件编程
null 稳定性高,可预测
null 不会因温度、湿度的影响产生误差,不需要精度组件
null 很高的性能价格比
在 LabVIEW 中可以用数字滤波器控制滤波器顺序、截止频率、脉冲个数和阻带衰减等参数。
本节所涉及到的数字滤波器都符合虚拟仪器的使用方法。 它们可以处理所有的设计问题、计算、内存管理,并在内部执行实际的数字滤波功能。 这样您无需成为一个数字滤波器或者数字滤波的专家就可以对数据进行处理。
采样理论指出,只要采样频率是信号最高频率的两倍以上就可以根据离散的、等分的样本还原一个时域连续的信号。假设对信号以△ t 为时间间隔进行采样,并且不丢失任何信息,参数 △
t 是采样间隔。
可以根据采样间隔计算出采样频率
根据上面的公式和采样理论可以知道,信号系统的最高频率可以表示为,
系统所能处理的最高频率是恩奎斯特频率。 这同样适用于数字滤波器。例如,如果采样间隔是 0.001 秒,那么采样频率是
系统所能处理的最高频率是
下面几种滤波操作都基于滤波器设计技术,
null 平滑窗口
null 无限冲激响应( IIR)或者递归数字滤波器
null 有限冲激响应( FIR)或者非递归数字滤波器
null 非线性滤波器
很多情况下通带的增益在均值附近稍微发生变化是容许的。
通带的这种变化被称为通带波动( passband ripple),也就是实际增益与理想增益之间的差值。在实际使用中阻带衰减
( stopband attenuation)也不可能无限接近 0,您必须指定一个符合需要的衰减值。通带波动和阻带衰减都使用分贝或者 dB
为单位,定义是,
其中 log10表示基值 10 的对数,而 Ai(f) and A0(f) 分别是频率在滤波前后的幅值。 例如,对于– 0.02 dB 的通带波动,表达式是,
这表明输入输出的幅值非常接近。
如果阻带衰减为– 60 dB,那么可以得到,
这表明输出幅值是输入幅值的 1/1000。
衰减值通常用不带负号的分贝为单位,但是默认为负值。
IIR 和 FIR 滤波器
另外一种滤波器分类方法是根据它们的冲激响应的类型。 滤波器对于输入的冲激信号( x[0] = 1 且对于所有 I<>0,x[i] =
0)的响应叫做滤波器的冲激响应( impulse response),如下图所示。冲激响应的傅立叶变换被称为滤波器的频率响应
( frequency response)。根据滤波器的频率响应可以求出滤波器在不同频率下的输出。换句话说,根据它可以求出滤波器在不同频率时的增益值。对于理想滤波器,通频带的增益应当为 1,
阻带的增益应当为 0。所以,通频带的所有频率都被输出,而阻带的所有频率都不被输出。
如果滤波器的冲激响应在一定时间之后衰减为 0,那么这个滤波器被称为有限冲激响应( FIR)滤波器。但是,如果冲激响应一直保持,那么这个滤波器被称为无限冲激响应滤波器 ( IIR) 。
冲激响应是否有限(即滤波器是 IIR 还是 FIR)取决于滤波器的输出的计算方法。
IIR 滤波器和 FIR 滤波器之间最基本的差别是,对于 IIR 滤波器,输出只取决于当前和以前的输入值,而对于 FIR 滤波器,
输出不仅取决于当前和以前的输入值,还取决于以前的输出值。
简单地说,FIR 滤波器需要使用递归算法。
IIR 滤波器的缺点是它的相位响应是非线形的。在不需要相位信息的情况下,例如简单的信号监控,那么 IIR 滤波器就符合需要。而对于那些需要线形相位响应的情况,应当使用 FIR 滤波器。但是,IIR 滤波器的递归性增大了它的设计与执行的难度。
因为滤波器的初始状态是 0(负指数是 0),所以在到达稳态之前会出现与滤波器阶数相对应的过渡过程。 对于低通和高通滤波器,过渡过程或者延迟的持续时间等于滤波器的阶数。
可以通过启动静止内存消除连续调用中的过渡过程,方法是将 VI 的 init/cont 控制对象设置为 TURE(连续滤波)。
对数字滤波器的详细讨论不是本书的内容,读者可参阅有关数字信号处理的书籍,下面我们具一个简单的例子说明在
LabVIEW 中如何使用数字滤波器。
练习 6-2 使用数字滤波器
目的:使用一个低通数字滤波器对实际采集的方波信号滤波。
1.创建前面板和流程图如下所示。
90.00
6
Filtered X
Lowpasswaveform
sample rate
number of samples
1
2.注意流程图。其中使用了一个数字滤波器模块( Functions 模板,Analyze) Signal
Processing) Filters 下的 Butterworth Filter.vi) 。先介绍一下这个 VI。
Butterworth 滤波器
filter type,按下列值指定滤波器类型
0,Lowpass 低通
1,Highpass 高通
2,Bandpass 带通
3,Bandstop 带阻
X,需要滤波的信号序列
sampling freq fs,产生 X 序列时的采样频率,必须大于 0。缺省值是 1.0。如果它小于等于 0 则输出序列 Filtered X 为空并返回一个错误。
high cutoff freq fh,高端截止频率。当滤波器类型为 0 (lowpass) 或 1 (highpass)时忽略该参数。
low cutoff freq fl:低 端截止频率。它必须满足 Nyquist 准则,即
0≦ f
i
<0.5f
s
如果该条件不满足则输出序列 Filtered X 为空并返回一个错误。 f
i
的缺省值是 0.125。
order,大于 0,缺省值是 2。
init/cont,内部状态的初始化控制。当其为 FALSE (default),初态为 0,当 init/cont 为
TRUE,滤波器初态为上一次调用该 VI 的最后状态。为了对一个大数据量的序列进行滤波,
可以将其分割为较小的块,设置这个状态为 FALSE 处理第一块数据,然后改设置为 TRUE
继续对对其余的数据块滤波。
Filtered X,滤波样本的输出数组。
3.在了解了这个滤波器的功能之后再来看上面的流程图。
这里 DAQ 部分将一个外部的 1KHz 的方波采集进来,采样频率是 100KHz,采到的方波一方面显示其波形,同时又送到滤波器的入口。滤波器类型设置为 Lowpass,其采样频率端直接连接到前面的采样频率控制端,因而也是 100KHz。另外,将采样频率除以 90 后作为低端截止频率,应该也是合理的,滤波器的阶数选为 6。这样的一个 VI 运行结果如前面板所示。
还需要指出的是原方波不以 X 轴对称,有直流分量,经这个低通滤波器后,直流分量还应当存在,曲线显示的确如此。
练习 6-2 结束。
6.3.2 曲线拟合
曲线拟合( curve fitting)技术用于从一组数据中提取曲线参数或者系数,以得到这组数据的函数表达式。
通常,对于每种指定类型的曲线拟合,如果没有特殊说明,都存在两种 VI 可以使用。
一种只返回数据,用于对数据的进一步操作,另一种不仅返回系数,还可以得到对应的拟合曲线和均方差( MSE) 。
LabVIEW 的分析软件库提供了多种线性和非线性的曲线拟合算法,例如线性拟合、指数拟合、通用多项式拟合、非线性 Levenberg-Marquardt 拟合等。
曲线拟合的实际应用很广泛。例如,
null 消除测量噪声
null 填充丢失的采样点(例如,如果一个或者多个采样点丢失或者记录不正确)
null 插值(对采样点之间的数据的估计;例如在采样点之间的时间差距不够大时)
null 外推 (对采样范围之外的数据进行估计,例如在需要在试验以后或者以后的数值时)
null 数据的差分(例如在需要知道采样点之间的偏移时,可以用一个多项式拟合离散数据,而得到的多项式可能不同)
null 数据的合成(例如在需要找出曲线下面的区域,同时又只知道这个曲线的若干个离散采样点的时候)
null 求解某个基于离散数据的对象的速度轨迹(一阶导数)和加速度轨迹(二阶导数)
下面是使用 LabVIEW 提供的算法得到的三种拟合的例子:线形拟合(左上),指数拟合(右上),多项式拟合(左下) 。
一般说来,采集得到的数据大都需要经过适当的处理,其中包括滤波、曲线拟合等。详细内容请参考有关资料。
第八章 数字 I/O
7.1 DI/O的基本知识
一般数据采集卡上都有 DI/O功能,用来实现数据采集的触发、控制及计数等功能。 DI/O
按 TTL逻辑电平设计,其逻辑低电平在 0到 0.7V之间,高电平在 3.4到 5.0V之间。
数采板上多路 (Line)数字 I/O 组成一组后被称为端口 ( Port) 。 一个端口由多少路数字 I/O
组成是依据其数采板而定的,在大多数情况下 4或 8路数字 I/O 组成一个端口。当读写端口时,你可以在同一时刻设置或获取多路 DI/O的状态。 MIO E 系列板卡有8路数字 I/O组成了一个端口,实际使用时这8路可以部分是输入,部分是输出。
数字量输入输出的应用分为以下两类:立即型(非锁存型)和定时型(锁存型) 。在立即型情况下,当你调用数字 I/O函数后立即更新或读取数字量某一路或端口的状态。在定时型情况下,你可以使用外部信号来控制数字量数据的传输。
LabVIEW 中关于 DI/O的 VI也分为低、中、高三个等级。
在以下几个不同的子模板中,
Data Acquisition? Digital I/O,顶层 — 用于较简单应用中的 Easy I/O VI。第二部分将讨论如何使用这些 VI。 LabVIEW基础教程中也将会详细讲述这些 VI。
Data Acquisition? Digital I/O,底层 — 是一些属于中级水平应用的 VI,主要用于需要时间或握手线方面的数字信号应用。这些 VI可用于单字节数据的传输。第三部分将详细讨论关于这方面数字量信号的操作。图 5-2 显示的是 Data Acquisition? Digital I/O 子模板。
Data Acquisition? Digital I/O? Advanced Digital I/O — 高级水平 DI/O VI 可用于作为创建其他数字 VI的基本模块。这些高级数字量 VI可用于立即型 DI/O和定时型 DI/O 。图 5-3显示的是 Data Acquisition? Digital I/O? Advanced Digital I/O 子模板。
图 5-2,Data Acquisition? DI/O 子模板
图 5-3,Data Acquisition? Digital I/O? Advanced Digital I/O 子模板
立即型 DI/O
立即型 DI/O 是最简单而且也是较经常使用的关于数字量方面的应用。它也叫非锁存型的 DI/O,所有带有 DI/O 接口的数采板都支持这种 DI/O 模式。在这种模式下,当 LabVIEW
调用函数后即可立即设置或获取某路 DI/O的状态。当某路 DI/O被设定为某一状态后,那么该路 DI/O 将一直保持这种状态直到其状态被重新设定为止。你可以通过软件改变某路 DI/O
是输入或是输出方式。下面将讨论 LabVIEW DAQ VI中的立即型 DI/O。
Easy I/O VI
使用 Easy I/O digital VI 你可以立刻输入或输出某一路(某一端口)的数字量。当你设置 DI/O VI iteration端为缺省参数时,每当你调用一次 DI/O 函数时系统将会按需要自动设置一次数采板。当你在一个循环中重复调用某个 DI/O 函数时,为了避免系统重复设置数采板,你可以设置 DI/O VI iteration 端为正数。这些 VI 可用于所有带有数字量输入输出的
NI数采板。
Write to Digital Line 设置某一端口中某一路 DI/O为逻辑高或者逻辑低状态 Device 是数采板的设备号( device number) ; Port number 是该路 DI/O 所在的端口号; Line 准备要写的该路 DI/O 的通道号; Line state 是指准备要写的该路 DI/O 的状态:高 (true) 或低
(false)。
图 5-4,Write to Digital Line
Read from Digital Line 读取某路 DI/O 的状态。 Device 是数采板的设备号( device
number) ; Port number 是该路 DI/O 所在的端口号; Line 准备要读取的该路 DI/O 的通道号; Line state 返回要读取的该路 DI/O 的状态:高 (true) 或低 (false)。
图 5-5,Read From Digital Line
Write to Digital Port 向某一指定的端口写一数字量,从而同时设定某一端口所有路
DI/O通道的状态。 Device 是数采板的设备号( device number) ; Port number 是准备要写的端口号; Pattern 是该端口要写的二进制或等同的十进制数字量。
图 5-6,Write to Digital Port
Read from Digital Port 读取某一指定端口所有路的 DI/O 通道的状态。 Device 是数采板的设备号( device number) ; Port number 是准备要读取的端口号; Pattern 是返回从该端口读取的数字量(十进制形式) 。
图 5-7,Read From Digital Port
如果在调用 Easy I/O digital VI 时发生错误,系统将会弹出一对话框显示出错代码,这时你可以终止或继续执行 VI。
注意,当你只调用一个 Easy I/O digital VI实例读或写某个通道或端口时,程序是不会出错的。
但是当再次调用函数时会通过改变移位寄存器的状态来重新改变 DI/O的设置,故你不能调用多个 VI实例来控制多个端口。 在这种情况下你可以通过使用下面将讨论的高级 VI来达到该目的。
高级 VI ( Advanced Vis)
使用高级 DI/O VI 也可以执行立即型 DI/O。 (实际上,Easy I/O VI 是由多个高级 VI所组成的) 。使用高级 VI你可以更高效的执行数字 I/O的读写工作,因为当你调用高级 VI 时,
它不会象使用 Easy I/O VI 那样每次运行时都需要去改变数采板的设置。高级 VI允许你使用通道屏蔽技术更新某一端口中数个 DI/O通道,而无须更新整个端口。根据高级 VI提供的错误信息你可以用来开发出自己错误处理程序。这些高级 VI 可用于所有带有数字量输入输出的 NI 数采板。
DIO Port Config 设置某个端口为写或读状态。 Device 和 port number设置板卡的设备号与端口号; Line direction map 设置端口为输入或输出状态;除了 TIO-10 与 MIO E 系列板卡外,其余板卡同一端口中所有各路 DI/O必须是同向的,即:同是输入或者同是输出。 task
ID out 的输出将用于下一 VI函数做为创建了一任务的唯一标识。
图 5-8,DIO Port Config V
DIO Port Write 根据已创建任务的标识 taskID立即更新端口的 DI/O通道状态。 pattern 输入的是一十进制数,当其换算为二进制时代表的是要更新的各路 DI/O通道的状态。举个例子来说:若设 pattern为 1(二进制 0001)那么将仅只设通道 0为高电位,若设 pattern为 15(二进制 1111)那将设通道 0,1,2,3为高电位。
图 5-9,DIO Port Write VI
使用 line mask 输入,你可以仅只改变你指定的 D /IO通道状态。 line mask 输入的是一十进制数字,该数字的值决定了那一个 DI/O通道的状态被更新。举个例子来说:若 line mask设为 1(二进制 0001)那么只有通道 0被更新,若 line mask设为 15(二进制 1111)那么通道 0,1,
2,3状态将被更新。未被包含在 line mask中的通道其状态将不会被改变。图 5-10 显示的两个例子就是使用 line mask来控制端口中那路 DI/O通道状态会被更新。你可以使用 Scale By
Power of 2 函数来选择单路通道或输入一十进制数直接选择多路通道。 在图 5-10a中,pattern
值设为 8(二进制 1000)时,通道 3将会被更新。在图 5-10b中,pattern值设为 6(二进制 0110)
时,通道 1,2将会被更新。假如你已设定该端口为输入状态,那么 error out 将会返回一个错误代码。
图 5-10,利用通道屏蔽技术来更新一个或多个通道的状态
DIO Port Read 根据已创建任务的标识 taskID来获得端口的 DI/O通道状态。 pattern 返回的是一十进制数,当其换算为二进制时代表的是各路 DI/O通道的状态。使用通道屏蔽技术你可以返回指定的通道状态,未被包含在 line mask中的通道其状态将在 pattern的返回值中被设为逻辑低(也就是 0) 。
图 5-11,DIO Port Read VI
立即型 DI/O 的应用
立即型 DI/O主要应用于:控制或监测继电器,作为计数器 Gate口的输入或者用于其他
TTL设备。例如可用立即型 DI/O控制 National Instruments SC-2062,SCXI-1160和 SCXI-1161继电器开关。
例 1—监测开关状态
本例演示如何使用 Easy I/O VI Read from Digital Line 来监测一外部开关的状态,关闭该开关后即初始化 LabVIEW测试程序。其硬件配置如图 5-12所示。
图 5-12,使用 DI/O监测开关的状态
在如图 5-13所示的程序框图中,Read from Digital Line连续不停的读取端口 0的第 0路通道的状态直到该通道状态为 TTL逻辑低(当开关关闭时),该 VI退出 While循环,然后运行下一测试子 VI。 Read from Digital Line设置端口为输入状态。
图 5-13,监测开关状态程序框图
例 2—继电器控制阀门
假如你想通过调节阀门来控制流入某个罐子中水的流量:当罐中液位低于某个位置时,
你想要打开阀门让水流入;当罐中液位高于某个位置时,你想要关闭阀门。通常情况下阀门是关闭的,所以你必须通过提供外部电力(如,120VAC)来打开阀门。图 5-14显示了如何使用 SCXI-1161继电器模块来控制这样一个系统。 SCXI-1161有 8个继电器(图 5-14仅显示了一个),每个继电器有一 COM位置,一 NC位置和一 NO位置。当通电完成后或处于歇息状态时,SCXI-1161即从 COM位置连接到 NC位置。
图 5-14,SCXI-1161控制阀门
在本例中,数采板上的某路数字量 I/O被设为输出模式后与继电器 0相连。 当向该路 DI/O
写 1时,与之相连的继电器会切换到 NO位置即连通电路从而打开阀门。下面图 5-15所示的
LabVIEW程序框图就是用高级 DI/O VI来控制该系统的。首先把 SCXI-1161模块的端口 0设为输出状态;用 Scale By Power Of 2函数创建一通道屏蔽仅控制通道 0; Get Tank Level 子 VI
返回罐子的液位。当液位低于设定的最低液位( LowLevel)时,程序即会向控制继电器的
DI/O通道写入 1从而打开阀门让水流入。与之相似,当罐子的液位高于设定的最高液位
( HighLevel)时,程序即会向控制继电器的 DI/O通道写入 0从而关闭阀门停止水的流入。
图 5-15,阀门控制的程序框图
继电器接触保护
我们经常连接电动机,阀门,螺线管以及白炽灯这些具有感应性质的负载到继电器上,
当继电器切换状态时就会产生巨大的反方向感生电动势。 因为这些感应负载存储了大量的能量,所以常常在这种情况下会毁坏继电器或者缩短其寿命。最好的方法就是使用一接触保护电路来限制在这种情况附加的感生电动势。你可以设置保护电路直接通过负载(在小型直流情况应用时,你可以把保护电路直接安装通过继电器接触段) 。假如你直接使用继电器,开启计算机时数采板会设置 DI/O 线的输入为高阻抗,你需要在 DI/O线上连接一电阻并在设置
DI/O为输出模式前将其设为一已知的状态。
练习 5-1
目标:使用一路 DI/O 完成一立即型数字量输出
建立一 VI可通过前面板的开关可控制试验盒上边 PA组的 LED灯的状态。当你开启开关时 LED灯亮,关闭开关时 LED灯灭。请使用 Data Acquisition? Digital I/O? Advanced Digital
I/O 模板中的 DIO Port Config 与 DIO Port Write VI(请不要改变该端口其他各路 DI/O的状态) 。你可以使用 Switch LED VI作为开始。
下图显示了试验盒上边 PA组的 LED灯与 DAQ板端口 0第 0路 DI/O的连接。
提示:确保 DIO Port Config VI 的 line direction map 的输入端是 -1,从而设置端口为输出模式。请记住 DAQ信号附件使用的是负逻辑:当你写假(逻辑低)时 LED则亮。且请使用通道屏蔽技术来更新 0路 DI/O。
练习 5-1 结束
练习 5-2
目标:在数字端口上执行立即型数字量输出
写一个 VI可随机产生一个 1到 4的整数,通过 DAQ信号附件端口 0上的 LED灯的状态来指示产生的是那一个随机数。假如是 1,则左边的 LED会亮而其他的灯全灭;假如是 2则最左边的第二个灯会亮,依次类推。使用 Data Acquisition? Digital I/O? Advanced Digital I/O模板中的 DIO Port Config 和 DIO Port Write VI。请使用 Digital Random Number VI开始。
练习 5-2结束
定时型DI/O
定时型 DI/O也叫做锁存型 I/O是第二种类型的数字量通信,它用来使用外部信号控制或作为握手信号的数据传输。 握手信号确保了在你初始化操作之前数采板或仪器已准备好了传输数据。
表 5-2显示的是数采板能有的锁存型 DI/O端口的数目。对于某些数采板,具备锁存功能的端口数目小于实际数采板上端口的总数目,这是因为这些数采板使用的是 Intel8255A
PPI芯片来控制数字线的。每个芯片是由 3个 8位的端口组成,当芯片上一个或多个端口设置为锁存型 DI/O时,这些端口中的某个端口上的几路 DI/O是保留用来作为控制握手信号的。
所以一个芯片上最多有两个端口被用做锁存型数字端口。
表 5-2,DAQ 板上能有的锁存型 DI/O 端口的数目
DI/O-32 型数采板有 4个 8路 DI/O端口。所有这些端口都可用做锁存型 DI/O。另外,这种类型数采板有另一定时型 DI/O功能即信号产生,是用一时钟产生握手信号来初始化数据传输。
这就意味着你可以以一定的频率输出或接受数字量数据。 这种方法在你的仪器或外部硬件不支持握手信号而你又想定时数据传输时是非常有用的。
定时型 DI/O VI
下面是使用握手线时传输数字量数据的高级 VI,
Digital Group Config 设置使用的 device 和 端口。 你设置 port list 组成了一组端口。 task
ID out 用来作为识别任务的标号。 group 输入是指已有一组端口,那么新设置将会替代已有的的设置。 group direction 输入端指定了组中的端口的方向。当该组支持握手线时
handshaking返回值为 1,否则为 0。
Figure 5-16,Digital Group Config VI
Digital Single Write 根据 task ID 任务标识执行数字量的输出。 opcode设定指定传输是否使用握手线。 Pattern list是一准备被输出的一维数组。 time limit设置决定传输时所分配的最大的时间。假如数据传输未在一定的时间内完成,函数将返回一个警告信息。 patterns written
输出将返回更新组( Group)后的组数。假如组中包含两个端口且 pattern list有 5个待输出的信号元素(即 2.5个组信号),那么仅只有前四个信号元素被输出且 patterns written的返回值为 2。
Figure 5-17,Digital Single Write VI
Digital Single Read 根据 task ID 任务标识执行组内端口的数字量读取。 Opcode输入端确定数据传输是否使用握手线。 Number to read确定是那一组输入被执行。 time limit设置决定传输时所分配的最大的时间。 假如数据传输未在一定的时间内完成,函数将返回一个警告信息。
Pattern list返回的是读取回的一维数组。 patterns read输出将返回读取组 ( Group) 后的组数。
Figure 5-18,Digital Single Read VI
DIO Single Read/Write,一中级 VI你可以在 Data Acquisition? Digital I/O模板中找到该 VI,
它是在我们上面讨论道的高级 VI的基础上作出来的。请记住:当你在循环中使用 DI/O时,
最好使用高级 VI以免象 DIO Single Read/WriteVI这样在循环中重复设置配置。
Figure 5-19,DIO Single Read/Write VI
Digital Single Read 与 Digital Single Write VI的执行是同步的; 当它们被调用后直到完成期间,其他 LabVIEW过程是不会被执行的。这种方式对于短急信息的传输来说是非常有效的,
但是当你想传输长数据流时就有可能长时间的占用计算机的资源。 在这种情况下你就可以使用下面将讲到的缓冲 DI/O。
例子 --- PC-PC 数据传输
你可以用有定时型 DI/O的数采板来完成通信应用,例如 PC-to-PC的数据传输。图 5-20
显示了使用两台都装有 DIO-32F数采板的计算机来完成 PC-to-PC的数据传输。在这个例子中
REQ 与 ACK线分别用于输入与输出的握手线信号。当软件调用操作且在 REQ线上接受到信号后,数采板就会执行一次数据传输。当执行完传输后数采板会在 ACK线上发出一个脉冲。
这样就可以保证数采板间数据传输的同步性。
Figure 5-20,DIO-32F 用于 PC到 PC 的数据传输
LabVIEW 框图
输出数采板
输入数采板
缓冲型 DI/O VI
假如需要大数量的数据传输,你也许希望使用非同步中断驱动式传输。这样不至于在传输数据时占用计算机的资源。使用这种方式传输数据时,一计算机内存缓冲被分配为后台线程输入或输出缓冲中。
中级 Data Acquisition? Digital I/O的模板中包含了用于建立数字量信号发生的 VI。表
5-3中显示的是缓冲式数字 IO程序设计的顺序,这些 VI与第四课表 4-1中的缓冲式模入和模出的程序设计顺序相类似。
表 5-3缓冲式数字 IO程序设计的顺序
DIO Config 设置的一组端口为输入或输出模式;创立数据缓冲,产生了任务唯一标识符,
它将会被下面的 DIO函数使用。
DIO Start 启动缓冲式 DIO操作。设定更新或读取的点数,当你输入 0时将连续操作。指定握手信号源:内部时钟用于信号发生,IO连接端口,或 RSTI连接端口。当执行信号发生时,
你也可以输入握手线信号的频率。
DIO Read 返回从数字量缓冲中扫描的数据;返回缓冲中的数据剩余量;返回在一定时限中操作的初始化是否成功信息。
DIO Write 用于输出操作中更新缓冲中的数据。当等侯的握手信号发生时,端口将被新的缓冲数据更新。假如在一定时限内握手信号没有出现,将返回一错误信息。
DIO Wait 等待与任务标识符 task ID.相关任务的数字量输入或输出操作的完成。
DIO Clear s停止操作,同时清除与 task ID任务相关的缓冲。
注意,当你使用这些 VI时,你的数采板必须支持握手信号。表 5-2显示了 NI公司生产的哪一些数采板支持握手信号。信号发生的功能只有 AT-DIO-32F,PCI-DIO-32HS,和
AT-DIO-32HS型号的数采板具有
下面的框图显示了使用缓冲式握手数字 IO VI的工作。每一个用于该框图的数字量 VI将在下面进行详细的讨论。
DIO Config VI,设置端口 1端口 1为一组输出组,同时为它们分配了数据缓冲。
DIO Write VI.将一个一维整形量数组存于缓冲中。 FOR循环使用自动索引输出方式创建了该数组。
DIO Start VI,设置 I/O接线端口为握手信号源,并启动输出操作。
DIO Wait VI.等待缓冲式输出操作完成。 DIO Clear VI.清除输出操作任务。
计数器
Counter I/O
对于一个成熟的数据采集和控制系统来说,它有一种非常重要的要求就是能操纵和协调多种不同时间参数和事件。这就需要某些硬件机构完成高精度的定时工作,那么这些机构中最基本的功能块就是计数器。 如果给予计数器非常精确的时钟你就可以把它应用到非常广泛的定时和计数应用之中去。例如:检测和分析数字波形,产生复杂的方波。
你可以在 NI的某些系列的多功能数采板上找到应用计数器的例子,那就是 AM9513A系统定时控制器。这个集成电路是由 5个 16位的计数器构成的,它们主要负责 DAQ操作的定时工作,如多用途定时及计数器应用。尽管 AM9513A是一多用途定时计数控制器,但它并不是专门为数据采集使用而专门设计的。因为 AM9513A仅有 5个计数器,假如你在运行某些同步操作时那么这些计数器将不够用,举个例子来说 AM9513A就没有足够的计数器来同时执行模拟输入、模拟输出和频率测量。
正是 AM9513A的局限性,所以 NI公司专门研制了数据采集控制器( System Timing
Controller (STC))用来控制 E系列的多功能数采板的定时操作。 DAQ-STC与现在其它公司生产的定时计数器相比,它具备有可扩展功能,低造价、低功耗的这些特点。这一块专用集成电路芯片总共有 10个 16位和 24位 20MHz的定时计数器。其中四个计数器用于控制模拟输入的定时操作,四个计数器用于模拟输出的定时操作;其它两个是留给用户使用的多用途,
UP/DOWN,24位 20MHz的定时计数器。
对于更高要求的定时计数操作,NI公司专门研发了 NI-TIO 集成电路芯片用于 6602和
445X系列数采板。这些定时计数器芯片是与 DAQ-STC相兼容的,同时又提供了其它的附加功能。每一个 NI-TIO芯片有四个能用于 80 MHz,20 MHz,100 kHz时基的 32位计数器,每一个计数器都有能被外部或内部信号控制的 GATE,UP/DOWN,SOURCE 输入口。如果使用预标定技术,NI-TIO能测量甚至频率高达 125MHz的连续,高速,重复信号的周期或频率。
因为直接低层编程使用定时计数器芯片是非常困难的,所以 LabVIEW提供了一系列高级的定时 /计数器库函数。在简化了定时 /计数器使用的同时并没有牺牲它们广泛的灵活性。
在 NI-DAQ6.5 有一个例程库,在该库中有每一种 NI定时 /计数器芯片的使用例子:
8253.llb,Am9513.llb,DAQ-STC.llb以及 NI-TIO.llb。下面将对计数器做一简单描述,接着将介绍 LabVIEW 中计数器 VI 以及使用计数器的例子。
计数器信号
计数器可以接收或输出 TTL兼容信号,一个 TTL高电位信号是被定义为其电位在 2.0和
5V之间的信号,TTL低电位是指其电位在 0到 0.8伏之间。一个能被计数器测得的信号,至少其特征不低于能被该计数器识别的最小的脉冲宽度,上伸时间、下降时间,请看图 6-1。
图 6-1计数器信号的特性参数
计数器操作
计数器是一能测量信号的变化过程或产生不同类型时间信号的设备。我们可以看一看如图 6-2所示的计数器的简化模型:一个 SOURCE输入口,一个 GATE输入口,一个 OUT 输出口,以及一个计数寄存器。数采板上分别对应的端口为,SOURCE n,GATE n,以及 OUT
n( n是指计数器的序号) 。
图 6-2,计数器的简化模型
你可以设置计数器对 SOURCE输入端口由高到低或由低到高的信号状态进行计数;并可以设置内部计数寄存器的计数方式为递增或递减方式;当你想知道信号状态改变的次数时,你就可通过读取内部计数寄存器的值即可知道。
GATE 口的输入端控制了计数器的计数操作。你可以将计数器设置为以下的几种门限工作方式:高电位时计数,低电位时计数,上升沿触发计数,下降沿触发计数,及无门限方式。高电位或低电位计数方式:只有当 GATE口的输入信号为高电位或低电位时,计数器才计数。上升沿触发计数或下降沿触发计数方:当 GATE 口接收到一由高到低或由低到高的状态变化信号后即开始计数。无门限方式:通过软件来初始化开始计数操作。
你可以使用计数器的 OUT口发生多种类型的波形,或者用于计数器的串级使用中,从而增大计数器的量程。 在一般模式下你可以设置计数器的端口输出一个脉冲或当计数寄存器已达到它的最大值时,输出一个切换状态作为一个终结计数。当接上一个时钟后你可以让计数器发出特定的频率和占空比的脉冲信号(一个占空比定义为,Phase 2 /[Phase 1 + Phase 2],
如图 6-3所示) 。输出的极性设置决定了初始化的 OUT口信号是低(正极性)或高(负极性) 。
图 6-3,计算脉冲的占空比
图 6-4显示了计数器 GATE 口工作为高电位计数时的情形,OUT口终结计数 显示了两种输出:脉冲,切换状态。
图 6-4,计数器 GATE 口工作为高电位计数
LabVIEW 计数器 VI
LabVIEW 计数器 VI 被分为了以下三个类型的模板,
Easy I/O VIs (Data Acquisition? Counter 模板 ):较简单的且经常使用的计数器 VI。如用于以下常用的定时计数操作:事件定时 /计数,产生单个脉冲,产生脉冲序列,测量脉冲宽度或周期以及频率测量。这些 VI使用时在前面板都有错误处理和详尽的操作指示。
Intermediate VIs (Data Acquisition? Counter? Intermediate Counter
模板 ):主要用于设置和控制计数器的操作,这些 VI比 Easy I/O VI更灵活。所有的中级计数器 VI都使用了 LabVIEW的错误处理,过你可以建立自己的错误处理路径。这些 VI使用时在前面板都详尽的操作指示。
Advanced VIs (Data Acquisition? Counter? Advanced Counter
模板 ):高级计数器 VI主要用于作为创建其他数字 VI的基本模块。这些 VI是最灵活也是最复杂的。典型的来说,用于需要多设置和控制的应用中。象中级计数器 VI一样,使用高级计数器 VI时你也可以建立自己的错误处理路径。
注意 当你打开 Windows? Show VI Info..,菜单后,便会弹出一窗口告诉你如何连接 source
口,gate口以及 output口。
在大多数情况下,我们使用 Easy I/O 计数器 VI,下面部分将介绍在不同情况下使用这些 VI。在后面的章节中将介绍中级和高级 VI的使用。
事件定时和计数
在本部分将介绍计数器的常用操作:事件定时 /计数,产生单个脉冲,产生脉冲序列,
测量脉冲宽度或周期以及频率测量。每个应用程序都将用到一个或两个 Data Acquisition
Counter VI 。在 LabVIEW中都有例程显示如何使用其中的每个 VI。
你可以把 Easy I/O VI Count Events or Time 用于事件定时 /计数 (图 6-5),例如 SOURE
输入口信号上升或下降沿出现的次数。 device 和 counter 输入端指定了是那一块数采板的那一个计数器端口将接收事件。 Source edge 确定该事件是上升沿还是下降沿。当 event
source/timebase 的输入端值小于或等于零时,计数器将对 SOURE口输入的信号进行计数。
当 event source/timebase被设置为有效的内部时钟频率时,计数器将对 SOURE口输入的内部时钟信号进行计数。根据你使用的数采板来决定你可用的有效内部时钟频率,如使用
DAQ-STC芯片的数采板其内部有效时钟频率可为 20MHz和 100KHz。 Counter size输入设置了最大计数容量,当超过该值后计数器将会溢出并重新清零。 DAQ-STC芯片上 24位的计数器在溢出前其最大计数容量为 16M。 start/restart输入端控制计数器启动 /停止操作。
图 6-5.事件定时 /计数 VI
count 输出端返回的是当前计数器寄存器的值。 seconds since start 返回自计数器启动后的时间值。 seconds since last call 返回自计数器寄存器被读取后的时间值。只有当 event
source/timebase 输入端为有效内部时钟时 seconds since start 与 seconds since last call的返回值才有实际意义。
练习 6-1
目标,对一已知的时钟信号的上升沿进行计数
1.打开 Exercise\lesson6.llb\Event countingCounting/Timing.vi,查看该 VI的前面板和后面框图。该 VI允许你重复启动或停止 Counter 1。这个计数器是对频率为 100 KHz的内部时钟的上升沿进行计数的。 Status输出指示了计数器当前是否在运行。 Count Events or Time输出全部都显示在前面板上。
前面板
程序框图
Count Events or Time VI (Data Acquisition? Counter 模板 )。
当你按下前面板 Start Counter 按扭后即启动计数器对内部时钟信号上升沿进行计数。在每次的 While循环中,该 VI都读取计数器寄存器的值并计算计数器被启动后的时间和上次被读取后的时间值,假如你按下前面板 Stop Counter按扭即停止计数器的运行。
Wait Until Next ms Multiple 函数 (Time & Dialog 模板 )。在本练习中控制 While循环的运行速度和每隔 1秒监视计数器的状态。
Status 局部变量 (Structures 模板 ).。在本练习中设置前面板的状态字符串来显示计数器是在计数还是在等候。
2.运行 VI。当你按下 Start Counter按扭后,即看到 Status输出为 Counter is counting。同时,
Counter Register Value 的显示应为每隔一秒递增 100,000。 Time Since Start显示你启动计数器后的时间; Time Since Last Call显示上次计数器寄存器被读取后的时间,因为 While循环是每隔一秒运行一次故该值应始终为 1。当你按下 Stop Counter后即停止计数器的运行,此时 Status显示为 Counter is waiting。
3.当按下 Quit按扭后即从该 VI中退出。关闭该 VI,不要保存任何改动。
练习 6-1结束,
发生脉冲
发生脉冲是计数器另一教常用的功能。你可以在 OUT口输出一个或一串脉冲。你可以使用 Generate Delayed Pulse VI发生一单个脉冲; Generate Pulse Train VI发生一脉冲序列。着两个 VI都在 Data Acquisition? Counter模板中。使用这两个 VI时你需要设定以下参数:脉冲极性,延迟,幅宽(延迟和幅宽之和为脉冲宽度)以及占空比。脉冲极性(如图 6-6所示)
决定了脉冲为高还是低。
Figure 6-6,脉冲极性高低的例子
注意 占空比定义如下,Duty cycle = Width / (Delay + Width),
发生单个脉冲
Generate Delayed Pulse VI (图 6-7) 输出一由 pulse polarity,pulse delay 和 pulse
width 参数决定的单个脉冲。 device 和 counter 输入端指定了是那一块数采板的那一个计数器输出单个脉冲。 gate mode设置了计数器工作的门限模式 (具体使用时,请给计数器的 GATE
输入口接上一外部的门限信号 )。 Timebase source决定了那一时钟用于延迟和幅宽。假如你使用内部时钟,那么数采板上的时钟作为延迟和幅宽的计时可达到秒的量级。假如你使用外部时钟,那么请你确保把外部的时基信号连接到计数器的 SOURCE端口上,此时延迟和幅宽的计时是以外部时基的周期数为单位的。 taskID输出包含了产生该脉冲所有设置的信息,是标识该任务的标识符。你可以把 taskID输出作为中级 Counter Start VI的输入参数从而可再发生同样的脉冲。
Figure 6-7,产生延迟脉冲的 VI
发生脉冲序列
用 Generate Pulse Train VI (图 6-8)可输出一系列由 pulse polarity,frequency,和 duty
cycle输入参数决定的脉冲序列。 Device,counter,和 gate mode输入参数的意义与 Generate
Delayed Pulse VI同名参数的意义相同。输入参数 number of pulses设定了脉冲序列的长度。假如你把 number of pulses设为零,那么该 VI将发生连续的脉冲序列。 TaskID输出包含了产生该脉冲序列所有设置的信息,是标识该任务的标识符。当你产生一有限长度的脉冲序列时将使用的是 taskID of counter-1返回值作为任务标识符。你可以把 taskID或 taskID of counter-1输出作为中级 Counter Start VI的输入参数从而可再发生同样的脉冲序列。
Figure 6-8,发生脉冲序列 VI
当你使用计数器发生一脉冲或脉冲序列时,用于启动计数器操作的信号与控制脉冲周期的时基信号并不是同步的。 在大多数情况下启动的脉冲信号并不是恰好在时基信号的上升沿时出现的。这也就是说,在启动发生脉冲时会有大致一个时基时钟周期的误差。图 6-9显示了使用高电位门限触发启动计数器操作时的这种误差。 这种误差在使用软件提供启动计数器操作信号时也存在。
Figure 6-9,启动计数器发生脉冲序列时的不确定性
练习 6-2
目标,使用计数器发生一个脉冲
在运行该练习之前,请将试验盒上的 GPCTR1 OUT接线端连线到模拟输入 ch0上。
1,打开 Exercise\Lesson6..llb\Counter Single Pulse VI 查看该程序的前面板和后面板框图
前面板
程序框图
2,打开并运行 Read and Chart VI,该 VI 会连续采集模入通道 1并将采得的数据显示到图表中去。当 Read and Chart运行后,运行 Counter Single Pulse VI。
3,在 Counter Single Pulse 前面板上设置脉冲的参数,按下 Generate Pulse 按扭后,你将在图表中看到计数器发生的脉冲。
4,停止这两个 VI的运行,在为保存任何改动的选择下关闭 Counter Single Pulse 。请不要关闭 Read and Chart.,你将在下面的练习中使用到该 VI。
练习 6-2结束
练习 6-3
目标,使用计数器发生一个脉冲序列
在运行该练习之前,
请将试验盒上 GPCTR1 OUT接线端接线到模拟输入的 ACH0上。
把试验盒上的 GPCTR0 OUT接线端接线到 PFI4接线端(计数器 1GATE口) 。
1,打开 Exercise\lesson6.llb\Counter Pulse Train VI 查看该程序的前面板和后面板框图
Generate Pulse Train VI (Data Acquisition? Counter 模板 )。在本练习中该 VI用产生一由前面板参数决定的脉冲序列。假如发生的脉冲序列是连续的,你可以通过按下前面板的 Stop
按扭来停止脉冲序列的发生。
前面板
程序框图
2,打开并运行 Read and Chart VI,该 VI 会连续采集模入通道 1并将采得的数据显示到图表中去。当 Read and Chart运行后,在 Counter Pulse Train 前面板上设置脉冲的参数,
运行 Counter Pulse Train VI,在图表中观察计数器发生的脉冲序列。
3,改变脉冲序列参数并输入,观察这些参数对脉冲序列的影响。
4,停止并关闭这两个 VI,请不要保存任何改动。
练习 6-3结束
脉冲宽度测量
你可以使用计数器来测量脉冲或脉冲序列的特性参数。 Measure Pulse Width or Period
VI (Data Acquisition? Counter 模板 )可用来测量连接到计数器 GATE口信号整个脉冲的宽度或幅宽的宽度。 Measure Frequency VI (Data Acquisition? Counter 模板 ) 可用来测量连接到计数器 SOURCE口脉冲序列信号的频率。这两个 VI都用到了计数器的门限计数功能 。
脉冲宽度或周期的测量
当你测量一脉冲宽度时,你需将被测的脉冲信号 Tpw 连接到计数器的 GATE口;将一已知频率的信号 Ts连接到计数器的 SOURCE口,如图 6-10所示。当计数器被设为高门限计数模式时,计数器会在 GATE口信号开始时对 SOURCE口的脉冲个数进行计数在 GATE口信号结束时停止计数。 此时你就可以用计数器寄存器的计数值乘以 SOURCE口信号的周期即可算出被测信号的脉冲宽度。用 Measure Pulse Width or Period VI时 SOURCE口用的是内部时钟,故你只需将被测信号接到计数器的 GATE口上即可。
Figure 6-11,Measure Pulse Width or Period VI
Measure Pulse Width or Period VI 输入参数 device 和 counter决定了是那一块数采板的那一个计数器用于测量脉冲信号的参数。 Type of measurement输入参数决定了你是想测量整个脉冲的宽度还是仅测量脉冲的高电位部分或脉冲的低电位部分的宽度。 timebase决定了用于被计数的内部时钟。若计数操作未在 time limit 时间限制内完成,timeout 输出为 TRUE。
Pulse width/period返回测量的宽度或周期(以秒为单位),count返回计数器寄存器的值。若
counter overflow? 返回值为 TRUE,这是有计数器溢出造成,此时你应当降低 timebase内部时钟的频率。 valid? 输出显示了是否有足够的内部时钟计数确保测量的脉冲宽度或周期值正确。
Figure 6-11,Measure Pulse Width or Period VI
练习 6-4
目标,使用计数器测量脉冲宽度或周期
运行程序前,请确保以做了下面的信号连接,
将试验盒上的方波输出 PULSE接线端引出方波信号到 PFI4(记数器 GATE口接上一方波信号。
1,打开 Exercise\lesson6.llb\Pulse Measurement VI,查看该程序的前面板和后面板框图。该
VI使用 Counter 1来测量连接到 GATE输入口信号的脉冲宽度或周期。计数器 SOURCE口接入的内部时 钟是由 Type of Measurement输入参数来决定的。
前面板
程序框图
Measure Pulse Width or Period VI (Data Acquisition?Counter
模板 )。在本练习中,该 VI使用来测量接到 Counter 1 GATE口上信号的脉冲宽度或周期的。其返回的错误信息可显示到 VI的前面板。
Attribute Node.。该属性接点是用来根据所选的测量类型来控制前面板与之对应的 Pulse
Width和 Pulse Period 控件是否变灰。你把鼠标放到前面板 Pulse Width和 Pulse Period
控件上后,单击右键从弹出的快捷菜单中选择 Create Attribute Node 即可创建对应的属性接点。请将这两个属性接点设为 Disabled(属性接点的操作是在 LabVIEW Basics II
Course 中详细介绍的) 。
2,请沿逆时针方向调节 DAQ 信号附件上的频率旋扭大致为 95~125Hz。把测量方式设为
High Phase后运行 VI,此时你应测得的脉冲幅宽大致为 0.008 到 0.0105秒。把测量方式设为 Low Phase后运行 VI,此时你应测得的脉冲宽度应与 High Phase方式相同。因为 DAQ
信号附件上发出方波的占空比是 0.5。
3,把测量方式设为 Rising to Rising后运行 VI,此时你应测得的脉冲宽度大致为 0.016 到
0.021秒或者是幅宽的两倍。因为此时测量的是整个信号的宽度。
4,将测量方式设为 High Phase 并旋动 DAQ信号附件上的频率按扭至非常高的频率,将 DAQ
信号附件上频率选择档设为最高的范围 (13 kHz–1 MHz)。此时信号方波的幅宽约为 500
ns 周期约为 1.0 ms 。因为计数器使用内部时钟为 20 MHz 故我们仍得到有效的测量结果。在后面板框图中将 timebase设为 100,000 Hz,运行后程序将返回 timeout 错误。因为计数器不能对 GATE口信号进行足够的计数,从而得不到有效的测量结果。
5,停止并关闭 VI,请不要保存任何改动。
练习 6-4 结束
频率测量
计数器也可用于测量脉冲序列的频率。通过对在给定的已知时间内的脉冲串个数进行计数即可计算出被测信号的频率。 给定时间间隔 TG是由连接到计数器 GATE口的脉冲信号控制的,如图 6-12。接到 GATE口必须是已知幅宽的脉冲信号,该信号是由外部信号源或数采板上第二个计数器提供的。 你用已知信号幅宽除以计数器在门限设置模式下读取的计数器寄存器的数值即可算出被测信号的频率。使用 Measure Frequency VI时,数采板上第二计数器提供门限脉冲,所以你需要将第二个计数器的 OUT输出口连接到第一个计数器的 GATE口,
将被测信号接到第一个计数器的 SOURCE口上。
注意 第二个计数器一般是使用数采板上紧邻使用计数器的上一个计数器。例如:你用于计数的计数器是 Counter 1,那么提供门限脉冲信号的计数器就是 Counter 0即把 OUT0接到
GATE1。
图 6-12,用于测量频率的信号连接
你可以使用 Measure Frequency VI (图 6-13)来测量频率较高的脉冲序列信号的频率 。
输入参数 device 和 counter决定了是那一块数采板的那一个计数器用于测量脉冲信号的参数。 Gate width设置了由第二个计数器 (counter-1)所发脉冲的幅宽(以秒为单位) 。 Counter
size设置了计数器对一未知信号能进行的最大计数值(对于 24位计数器来说为 2的 24次方) 。
假如你需要对 Measure Frequency VI 中的 counter-1进行门限触发,请给 counter-1计数器的
GATE输入口上接入触发信号; 同时你必须正确的设置 gate mode 与 maximum delay to gate
参数。例如:当这些设置好了,只要 counter-1计数器在其 GATE输入口上接收到一上升沿触发信号后,counter-1即在其 OUT口输出一已知的接于 counter GATE输入口的门限脉冲。
Frequency返回测得的被测信号的频率(以 Hz为单位) 。 Valid? 返回参数指示是否有错误发生。
图 6-13,Measure Frequency VI
练习 6-5
目标,使用计数器测量未知信号的频率
在运行该练习之前,请确保了你的 DAQ信号附件已有了下面的连接,
把一方波信号接到 Counter 1的 SOURCE口上。
把 Counter 0的 OUT口输出连接到 Counter 1的 GATE口输入上。
1,打开并查看 Exercise\Lesson6.llb\FrequencyMeasurement VI.。 该 VI将测量连接到 Counter 1
上脉冲序列信号的频率。 Counter 1 在其 GATE口输入为高电位时会对其 SOURCE口的脉冲个数进行计数。你也可以把 Counter 1的门限计数方式设为低电位模式,即当其 GATE
口输入为低电位时会对其 SOURCE口的脉冲个数进行计数。你可以在 VI的前面板上通过
GateWidth来设置门限脉冲的幅值宽度,LabVIEW会自动设置 Counter 0输出门限脉冲。
Measure Frequency VI (Data Acquisition? Counter 模板 )。 本练习中这个 VI将用来测量连接到 Counter 1的 SOURCE口的信号的频率。这个 VI会返回错误信息并显示的前面板上。这个
VI会自动根据前面板 Gate Width参数来设置另一计数器输出已知幅宽的脉冲序列信号。
Unbundle 函数 (Cluster 模板 )。将用于对 Measure Frequency VI 返回的错误信息进行解包并显示到前面板上。
2,请逆时针旋转 DAQ信号附件的频率旋扭。把 Gate Width设为 1后运行程序。此时频率的测量值应在 95 Hz与 125 Hz之间。重新运行几次程序,数次同样频率信号频率的测量值有可能有稍微的差别。这是由于门限信号电位为高时的时刻与 SOURCE口出现第一个用于计数脉冲时刻的时间差异不同而造成的,如图 6-14所示。
Figure 6-14,导致频率测量不精确的原因
3,请将 DAQ信号附件的频率旋扭旋到最大频率处,把 Gate Width设为 20秒后运行该 VI。你将会看到一计数器寄存器溢出的错误信息。这是由于而被测信号频率过高,从而导致在门限幅宽为 20秒期间计数器对被测信号计数已超过其计数寄存器的最大计数容量,从而出现溢出的错误信息。当 DAQ信号附件的频率旋扭旋到最大处,其产生信号的频率约为
1 MHz。
4,关闭 VI,请不要保存任何改动。
练习 6-5 结束
其他附加有用的Counter VI
计数器的分频设置
Down Counter or Divider Config VI (Data Acquisition? Counter?
Intermediate Counter 模板 ) 是一当预设事件次数出现后可发生脉冲的 VI。例如:你把
timebase/timebase divisor设为 100 Hz / 50,那么计数器将每隔 50个时基脉冲在 OUT发出一个脉冲或切换电位状态,其频率应为 50*100 Hz = 2 s 。当你启动该操作时,请将该 VI的 taskID
输出接到 Counter Start VI (Data
Acquisition? Counter? Intermediate Counter 模板 )上。
Figure 6-15,Down Counter or Divider Config VI
CTR Control
The CTR Control VI (Data Acquisition? Counter? Advanced Counter
模板 ) 可用于由 control code 输入参数决定的关于计数器控制方面的所有操作:启动,停止,
读取以及重置计数器。 CTR Control VI 也能控制数采板上的 FREQ_OUT通道输出根据 fout
data参数指定频率的占空比为 0.5的脉冲序列且并不占用数采板上的计数器。你可以通过设定 control code为 7 (enable FREQ_OUT)来启动 FREQ_OUT输出;设定 control code为 8(disable
FREQ_OUT)来停止 FREQ_OUT输出。
Figure 6-16,CTR Control VI
CTR Group Config
CTR Group Config VI (Data Acquisition? Counter? Advanced Counter 模板 )可将一个或多个计数器合成为一组。 Device设定数采板的设备号,group是根据 counter list数组设给该组计数器的唯一组号。 task ID返回值是标识该任务的标识符; error in 和 error out包含有错误信息。请记住该 VI需在所有计数器操作前运行。
Figure 6-17,CTR Group Config VI
CTR Mode Config
CTR Mode Config VI (Data Acquisition? Counter? Advanced
Counter 模板 ) 根据 task ID,config mode,source,timebase signal,gate parameters,output
type,和 output polarity参数来对计数器进行设置。 error in 和 error out包含有错误信息。
该 VI并不启动计数器操作。在计数器运行时的情况下,你并不需要使用该 VI,除非你想改变计数器的门限和输出工作状态。
Figure 6-18,CTR Mode Config VI
下面你将使用 Advanced Counter VI来跟踪一正交编码器的位置。但是首先要提醒你,
关于正交编码器的操作只能用于 DAQ-STC和 NI-TIO芯片。
正交数码盘
数码盘是一能将线性或旋转位移转变为数字或脉冲信号的变送器,通常安装在旋转的轴上。它能发出对应于轴旋转运动状态的脉冲序列信号。正交数码盘是较常用的有两通道用来监测轴位置的递增式数码盘。 对于转子每旋转一定角度,递增式数码盘将会产生一个脉冲。
因此,递增数码盘的精度是由转子旋转一周中有数码盘能发生多少个脉冲数目来决定的。一般常使用的数码盘并不输出绝对位置信息。 但是正交数码盘使用了两个相位差为 90度的跟踪通道(如图 6-19),所以正交数码盘上的通道 A和通道 B可以显示旋转的位置和方向这两个信息。
Figure 6-19,正交编码器输出通道 A 和 B
假如通道 A超前通道 B,那么旋转的方向为顺时针方向;假如通道 B超前通道 A,那么旋转的方向为逆时针方向。这样通过监测通道 A,B信号的脉冲个数和相位差,你就可以跟踪旋转的位置和方向。
DAQ-STC 计数器的增 / 减计数输入
NI E系列数采板上的 DAQ-STC 定时 /计数器可用于计数器的增 /减计数,DAQ-STC上的计数器除了有 SOURCE口和 GATE口外还有 UP_DOWN口。当 UP_DOWN口接入的 TTL信号为高电位时,计数器将会递增计数;当 UP_DOWN口接入的 TTL信号为低电位时,计数器将会递减计数。这样,我们就可以来监测正交数码盘的旋转方向。
假如正交数码盘输出的直接是 TTL信号,那么你可以将输出的信号直接接到 DAQ-STC
或 NI-TIO上。否则你需要在数码盘和计数器之间加上信号调理电路。通道 A将接到计数器的
SOURCE口上,通道 B将接到 UP_DOWN口上。当数码盘顺时针旋转时,A将超前 B 90度。
这就意味着当通道 A信号的状态为由高到低时,通道 B上信号为高电位状态,此时计数寄存器将对 A的下降沿切换状态进行递增计数;当数码盘逆时针旋转时,B将超前 A90度。这就意味着当通道 A信号的状态为由高到低时,通道 B上信号为低电位状态,此时计数寄存器将对 A的下降沿切换状态进行递减计数。
你现在可以使用 Counter 0来跟踪 DAQ信号附件上旋转正交数码盘。关于正交数码盘的详细资料,请查阅 Application Note 084,Using Quadrature Encoders with E Series DAQ Boards。
Measure frequency-Easy(9513).vi
1
device
1
counter
0.00047996
period (s)
YES
valid?
2.00
gate width (s)
2083.500
frequency (Hz)
NO
overflow?
NO
timeout?
one counter
number of counters to use
For instructions select
File >> VI Properties >> Documentation