自1986年起,众多从事测试仪器研发的工程师便开始采用由National Instruments Inc.精心研发的LabVIEW软件。该软件凭借其独特的图形化用户界面设计,为用户提供了便捷的编程途径——用户无需编写传统的计算机代码,而是通过在各个功能模块之间进行可视化连接(即“布线”)来实现仪器功能的编程。借助LabVIEW,工程师们可以构建功能极为复杂的测试流程,这些流程可能包含闭环反馈机制以及用于操控各类设备(如相机和电压表)的功能模块。
尽管无需依赖传统文本编程即可构建相对复杂的测试程序的理念颇具吸引力,但目前尚未出现任何能够与LabVIEW相媲美的开源替代品。这一现象或许与National Instruments公司对LabVIEW中的诸多核心概念申请了专利不无关系。
然而,一款名为MyOpenLab的开源软件在界面设计上与LabVIEW颇为相似,展现了潜在的替代可能性。据考证,MyOpenLab项目起源于德国一位程序员的个人业余开发,该项目于2006年首次问世,目前由哥伦比亚的另一位程序员负责维护。其知名度的提升,很大程度上得益于西班牙某大学教授发布的系列教程视频以及相关的在线短期课程推广。(值得一提的是,另一个名为Pylab-works的开源项目也曾拥有类似的界面设计,但现已停止更新。)
值得注意的是,MyOpenLab在开发适用于Raspberry Pi和Arduino等嵌入式平台的控制程序方面表现出色。(此外,存在一款LabVIEW编译器,可让程序在Raspberry Pi上运行。尽管LabVIEW本身能在PC端运行并指导Arduino执行特定指令,但其代码无法直接在Arduino硬件上执行。)
LabVIEW与MyOpenLab之间的相似性在在线技术论坛上引发了关于两者核心差异的深入探讨。MyOpenLab的吸引力显而易见。LabVIEW的基础授权费用约为每年400美元,且随需求增加而持续攀升。虽然存在一款名为LabVIEW Home Bundle的爱好者版本,一次性收费仅为50美元,但该版本明确标注为“仅限非商业、非工业及非学术用途使用”。
尽管MyOpenLab在功能表现上可能部分模拟了LabVIEW,但其技术架构基于Java语言,与LabVIEW的内部实现方式存在本质区别。深入研究两个程序的架构差异,将有助于更全面地理解它们各自的优劣势。
LabVIEW的核心编程理念在于数据流编程。这种编程模式的正式定义是:应用程序由多个处理单元构成,这些单元通过数据链路交换信息。只有当所有输入数据均有效时,相关操作才会启动。此外,用户可以在不修改内部逻辑的前提下,通过重新配置处理单元间的连接来构建不同的应用程序。
更直观的理解方式是借鉴电子表格这一广泛应用的可视化工具。每个电子表格单元格可视为一个独立处理单元,单元格间的关联则通过公式及单元格引用实现。若要改变单元格间的连接关系,用户只需调整公式中的单元格引用即可。
将LabVIEW类比于电子表格的运作方式,其基本原理相似:LabVIEW以图形化的“模块”替代电子表格单元格,模块间的数据流则通过“导线”实现连接。(另一种常见的类比是将LabVIEW视为流程图,其连接同样由导线构成。)
LabVIEW的编程术语相较于电子表格更为专业。电子表格采用独立的工作表结构,而LabVIEW中对应的概念是“虚拟仪器”(VI)。每个VI包含三个主要部分:框图、前面板和连接器面板。一个VI可以通过连接器面板调用或引用其他VI。前面板由各种“控件”组成,用于向VI传递信息,而“指示器”则根据VI的输入和内部处理结果展示输出数据。
框图内包含用于操作控件并向指示器提供数据的结构和功能模块。这些元素统称为“节点”,节点之间通过“导线”相连。因此,在电子表格中,用户可以设定一个单元格来显示其他两个单元格数据的和。在LabVIEW中,用户可将两个控件和一个指示器连接到特定功能模块,使指示器显示这两个控件的累加值。
LabVIEW与电子表格的类比在VI的嵌套使用上有所局限,因为一个VI不仅可以独立运行,还能作为模块被拖入其他VI的框图中。这种设计优势在于,用户可以在将VI整合进更大系统前,对每个VI进行独立的测试验证。
通过拖放VI构建程序的便捷性固然值得肯定。然而,当面对复杂功能需求时,LabVIEW程序的构建可能需要用户具备对LabVIEW语法和内存管理机制的深入理解。
一旦VI的层级结构确定,LabVIEW系统将自动将这些模块编译成可执行的机器代码。
与LabVIEW不同,MyOpenLab的架构并非基于数据流编程,而是采用事件驱动模式。在事件驱动系统中,程序的执行流程由事件触发决定。常见的事件包括鼠标点击、键盘输入以及其他程序间传递的消息。鉴于图形用户界面的固有特性,其设计通常围绕事件驱动架构展开。
实现事件响应功能的标准方法通常涉及构建主循环,该循环以类似工业可编程控制器的模式持续监听事件。当系统检测到特定事件时,会调用相应的事件处理程序。对于GUI应用程序,事件处理程序主要负责响应鼠标点击和键盘输入。就MyOpenLab而言,其事件处理程序可能专注于检测模块间的导线连接状态及功能模块的输入信号等。
尽管MyOpenLab基于事件驱动架构,但LabVIEW同样支持事件驱动的功能实现。这主要通过LabVIEW内置的“事件结构”实现。在此语境下,“结构”特指控制程序执行流程和时序的图形化组件。从这个角度观察,LabVIEW可被视为数据流编程与事件驱动编程的有机结合体。
读者或许会注意到,事件驱动程序中的循环和事件处理程序与基于流式编程中的调度功能存在相似之处。在流式编程模型中,类似功能由“调度器”实现,其职责是决定是否对模块间的连接进行操作。数据流程序与事件驱动程序的关键区别在于,数据流程序的调度器无需执行任何循环,仅在有数据需要处理和输出位置可用时才会运行。通常情况下,这种架构使得基于流式编程的应用程序在运行效率上优于事件驱动程序。
需要特别指出的是,本文讨论的“循环”特指软件内部的逻辑结构。LabVIEW和MyOpenLab均可用于创建多层嵌套的循环结构(如信息循环、堆叠序列等)。但这些循环是由用户在程序中明确构建的。
MyOpenLab采用Java语言开发。Java作为一种编译型语言,其应用程序通常先被编译为字节码,再由Java运行时环境(Java Runtime Environment, JRE)执行。JRE通常包含Java虚拟机(Java Virtual Machine, JVM)等关键组件。关于Java生态系统的关键特性是,所有这些组件(包括MyOpenLab本身)均提供免费版本。
将LabVIEW与MyOpenLab进行比较的主要目的之一在于分析两者在用户界面设计上的共通之处。在MyOpenLab中,程序的工作区域被称为“电路板”。该软件同样配备了前面板功能。LabVIEW使用“虚拟仪器”概念,而MyOpenLab则采用“可视化模型”设计。在MyOpenLab界面中,用户可通过点击按钮图标执行多种操作,包括启动/停止模拟、逐步执行序列、数据显示、模拟时间调整等。为连接不同功能模块,用户需先点击目标输出端,再选择相应模块的输入端进行连接。
由于MyOpenLab基于Java开发,其内部组件的Java代码是可被修改的。但从其文档来看,尚不清楚MyOpenLab是否支持使用非Java语言编写的子程序或插件。相比之下,LabVIEW则具备更广泛的兼容性,能够调用多种语言编写的代码模块以及动态链接库(DLL)。
执行外部编写的代码的能力,正是LabVIEW与MyOpenLab之间的重要差异。LabVIEW作为一个功能更全面、技术更成熟的平台,其手册中有专门章节(长达302页)详细说明如何集成外部代码。而MyOpenLab的文档主要由10份用户指南构成,每份约60页,且以西班牙语为主要语言。(值得肯定的是,Google翻译工具能够较好地将这些文档翻译成英语。)
尽管如此,当面临复杂任务时,LabVIEW程序可能变得异常庞大且难以管理。此外,开发高级LabVIEW程序似乎需要与掌握其他高级编程语言相当的技能水平。
例如,在LabVIEW的Wikipedia讨论页面上,可以看到关于该软件优缺点的详细辩论。该页面设有专门章节讨论LabVIEW本身,并探讨是否应在Wikipedia的LabVIEW条目中包含某些批评意见。许多批评意见以“LabVIEW无法实现XX功能”的形式出现,这些观点通常来自长期使用LabVIEW的专业人士。其他专业人士则会对这些批评提出反驳,指出LabVIEW实际上具备所述功能。然而,关于如何实现这些功能的解释往往隐藏在详尽的LabVIEW文档中,或使用不够清晰的术语表述。
当然,MyOpenLab并不具备LabVIEW的所有高级功能,某些在LabVIEW讨论页面上被提及的特性,其用户可能并不了解。因此,两个软件最适合的应用场景存在明显差异:LabVIEW对于处理复杂的仪器控制和测试任务仍具有不可替代的价值;而MyOpenLab可能更适合需求相对简单的应用场景。