1、基于 Python 的虚拟仪器技术研究及实现来源:现代电子技术随着计算机技术、测量仪器技术以及软件技术的高速发展,微机以及 DSP 提供了强大的计算能力使得在一定的实时性要求下,软件可以代替许多原来由硬件完成的功能,这标志着“软件即仪器(The software is the instrument)”时代的到来。它的出现彻底改变了传统的仪器观,开辟了测量技术的新纪元。虚拟仪器的基本思想是利用计算机来管理仪器、组织仪器系统,进而逐步取代仪器完成各种功能,最终取代传统电子仪器。虚拟仪器实质上是软硬件结合、虚实结合的产物,利用高性能的模块化硬件,结合高效灵活的软件来完成各种测试、测量和自动化的应用。
2、在虚拟仪器系统中,硬件通常仅仅是为了解决信号输入输出,软件才是整个仪器系统的核心所在。与传统仪器相似,虚拟仪器一般由 3 部分组成,即数据采集与控制、数据处理与分析、数据显示。传统仪器只是将这 3 部分功能的部件放在一个仪表机箱里,而虚拟仪器则是功能意义上的仪器,是具有仪器功能的软硬件的组合体,它并不强调物理上的实现形式。虚拟仪器的功能由用户自己定义,仪器制造商只需提供基本的软硬件,如信号调节器、信号转换器等,真正需要什么样的仪器功能是用户自己的事情。虚拟仪器不像传统仪器那样几乎完全依赖硬件。硬件在这里只是为了解决信号的输入输出,软件才是虚拟仪器的关键。虚拟仪器减少了信号每次经过硬件引起的误差
3、,从而测量结果更准确。虚拟仪器价格低,开发和维护费用也比传统仪器低得多,而且技术更新快。1 基于 Python 的虚拟仪器开发美国 NI 公司推出的图形化虚拟仪器专业开发平台 Labview 采用独特的图形化编程方式,编程过程简单方便,已经成为目前最受欢迎的虚拟仪器交流开发平台。另外还有惠普公司的HPVEE 以及微软开发的 Visual C+。但是往往上述的软件在虚拟仪器开发中做不到图像和数据处理两方面兼得。比如 Labview 在界面开发上有很大的优势,但在数据处理方面不尽人意。而且很多仪器在处理复杂信号的时候需要借助 Matlab 强大的信号分析处理能力,但是一般仪器厂家提供的分析软件不支
4、持与 Matlab 的接口,将两者功能进行结合也有难度。另外LabVIEW 后期修改程序比较麻烦,一旦要改,改动的地方就比较大,这对于较大型的程序是很不利的。虚拟仪器的使用者更希望能够方便的修改软件配置,满足不同个体的需求,Labview 在这一点上有局限性。Python 是一种开源的脚本编程语言,由可移植的 ANSI C 编写,可以轻松驾驭windows、Linux、Mac 等主流操作系统,可移植性极强。同时 Python 具有强大的扩展性,可以嵌入 CC+编程的程序中,所以也能实现多种语言的混合编程。Python 是面向对象(OOP)的编程语言,结构化的或过程性编程可以让我们把程序组织成逻
5、辑块,重复或重用,这一特性应用于虚拟仪器的开发正好可以弥补 Labview 后期修改程序复杂这一致命问题,同时也是一项有益的探索。Python 拥有着丰富的扩展模块和函数库。PYQT 可以轻松开发出优质的 GUI 界面。NumPy 相当于 Matlab 的 Python 版本,它提供了矩阵、线性代数、傅里叶变换等的解决方法,包含:N 维矩阵对象、性代数运算功能、傅里叶变换、Fortran 代码集成的工具、C+代码集成的工具。下面主要从对象分解,GUI 开发,以及数据处理 3 个方面进行研究探讨 Python 在开发虚拟仪器方面的优势及可能潜在的问题。11 对象分解用面向对象的思想来看待客观事物
6、时会把一个整体看成由许多不同种类的对象组合而成。每一个对象本身有他自己的内部状态和动作,称之为对象本身的属性和操作。不同的对象之间都是相互联系,相互作用的,由此构成了一个完整的整体。在虚拟仪器的开发过程中我们也可以运用这种思想将一个待开发的仪器整体分解成多个对象的组合,对每一个对象划归为一个整类,然后由这个类衍生出实例类,最后再把一个个的对象个体整合成一个整体,如图 1 所示。比如在虚拟仪器开发过程中,通常需要设计各式各样的按钮,包括波形调节、通道选择、波形显示、数据处理等等。如果一个一个地去设计编程,必然大大复杂化了开发进度。在这里,运用面向对象的思想,我们可以把按钮抽象为一个按钮类,并定义
7、其各种一般性的特性,不同大小,不同功能,不同形式的按钮无非只是这个普遍按钮类的一个特殊性实例化。数据处理也是同样的道理,不管是滤波,FFT,卷积,都可以看成是一种数据处理方法类的实例化。这样,一个仪器的开发就被分割成 N 个对象的设计,最后只需实现各个对象之间的协调作用即可。12 基于 PYQT 的 GUI 开发人性化的用户操作界面(GUI)是虚拟仪器必不可少的一个组成部分。PYQT 是 Python 与QT 库的混合体,拥有近 300 多个类和接近 6 000 多个函数与方法。基于面向对象思想的虚拟仪器开发过程中,对象与对象之间的信息交流、互动尤为重要,也就是所谓的事件处理。任何 GUI 程
8、序中,事件都是最重要的部分。在 PYQT 中,采用信号和插槽这一机制来处理事件。当用户点击按钮,拖动滑块等操作时都会产生信号,同时环境也会产生信号,比如时钟的信号,插槽是一种针对信号进行处理的方法。所有从 QObject 或其子类派生的类都能包含信号和槽,当某个对象的状态发生改变时,相应的信号就由该对象发射(emit)出去,并不需要知道另一端是谁在接受这个信号,从而真正意义上实现信息封装。PY QT 的信号与槽机制相当灵活,可以讲多个信号与单个槽相连,也可以将单个信号与多个槽进行相连,甚至一个信号还能与另一个信号相连。 PYQT 中将信号与槽相连只需用到 QObject 类中的 connect
9、()方法。创建 PYQT 界面的几个步骤:1)使用 QtDesigner 创建 GUI;2)在属性编辑器中修改部件的名字;3)通过 pyuic4 工具生成一个 Python 类;4)通过 GUI 对应的类来运行程序;5)通过设置自己的 slots 来扩展功能。先用 QtDesigner 生成整体 GUI 框架,保存为 Formui 文件。Windows 下运行 cmd,在C 根目录调用 pyuic4 命令:pyuic4 FormuiFormpy,将 PYQT 生成的 UI 文件转成 py 文件,然后自定义 startpy 直接调用生成的 py 文件,运行 startpy 就可以显示创建的GUI
10、 界面。然后对 GUI 的每一个控件编辑其对应的信号与槽,比如在文中实例中的“关闭”按钮,调用 connect()方法绑定点击按钮的“clicked()”信号与槽函数“close()”,这样当我们鼠标点击“关闭”按钮的时候程序就会退出。与此类似,绑定其余按钮的功能。这里还可以调用:PyQt4QtCorepyqtSignal(types,name)创建一个或多个重载绑定信号作为类属性。其中 type 确定信号的 C+识别标志,类型可以是 Python 类型或 C+类型名称的字符串,也可以是类型的一组列表,在列表情况下,每一项定义了不同重载方法,第一项为默认值。Name 是信号的名称,如果省略则使
11、用属性的类的名称,这只能作为一个关键字参数。槽函数(slots)的设置是整个 GUI 的核心,基于 Python 面向对象的优势,我们可以调用各种父类,父类方法,自定义类,自定义方法等等作为槽函数与相应的信号相绑定,实现程序的重复利用,并且可以在后期较容易的扩展程序的功能,通过这种代码复用可以大大缩短虚拟仪器开发周期。13 NumPy 的数据处理虚拟仪器一般都会带有显示屏幕,有的仪表显示数字,有的仪表则显示图形。通过软件的形式显示测量结果,一般需要对采集数据进行大量的数学运算,比如信号调幅、调频、滤波、数字信号处理等等,数据处理是虚拟仪器不可或缺的一部分,而且数据处理一般要求高效准确。NumP
12、y 相当于 Matlab 的 Python 版本,继承了 Matlab 的强大数据处理能力。NumPy提供两种基本的对象 ndarray (N-dimensional arrayobie ct)和 ufunc(universal function object)。ndarray 是存储单一数据类型的多维数组,而 ufunc 则是能够对数组进行处理的函数。NumPy 的核心是 ndarray 对象,它是一个封装好的,只能存储同个类型数据的多维数组。NumPy 里,数组元素对数组元素的操作是用 C 写的,并预先编译好了以提高操作速度。NumPy 不仅能保证足够快速的计算处理,还继承了 Python
13、 语言代码简洁的特性。比如需要对一个给定的多维数组 x 进行 FFT 变换,只需调用 np.fft.fft(x)就可以得到变换的结果。2 方案设计与验证基于上述的讨论,设计完成了一个虚拟频谱分析仪,该仪器的工作原理是通过设置仪器相关的参数对采集信号进行实时显示,而后通过滤波加窗等处理进行频域分析,得到幅值谱、相位谱、自相关函数、相干函数等的过程。仪器系统的处理流程如图 2 所示。在仪器的波形显示部分,这里调用了 Tabwidget 控件,通过控制 Tabchange()信号实现时域波形和频域波形的显示及切换。Tabwidget 本身无法充当画布功能,也就是说不能直接在上面显示波形。因此,在 T
14、abwidget 的 2 个 tab 标签中分别嵌入一个 QwtPlot 控件,它可以提供一个二维的坐标图,让我们在上面绘制曲线、刻度值等我们想要表达的图形数据信息。调用 setAxisTitlle(xBottom,String)方法和 setAxisTitlle(vLeft,Str4ng)方法可以改变坐标轴横坐标及纵坐标的名称。同时还需要创建一个 QwtPlotCurve 用来控制 QwtPlot 上的曲线类型,它可以设定线的样式(实线或虚线)、线宽、颜色等。取得需要显示的波形数据后,通过 setData()方法,先将数据给予 QwtPlotCurve,然后由 QwtPlot Curve 通
15、过调用attach()方法将波形绘制到 QwtPlot 上,最后通过 QwtPlot 类的 repoh()方法将波形显示在GUI 界面的 Tabwidget 控件中。输入信号后,调用 combobox 控件的 GetWindowText()方法取得采样频率,采样点数等参数信息,通过绑定“开始采样”的“clicked()”信号触发相关槽函数将波形显示在窗口上。这里放置了 3 个 RadioButton,并把他们嵌入到 Gmup Box 里作为一个整体,通过他们的 Checked 属性,获取相应窗函数信息对信号进行加窗处理,分析。仪器界面的效果图如图 3 所示。3 结束语Python 是一门年轻、开源、充满活力的脚本编程语言。文中以 Python 为核心,结合 PYQT 把面向对象思想应用于虚拟仪器开发,使用户可以根据自身需求方便地修改程序以增减仪器的系统功能或规模,而且可以充分实现程序的重复利用。用 Python 开发虚拟仪器层次清晰,周期短,代码易修改。在一定程度上比LabvIEW 具有更大的优势,具有广泛的研究前景。